Skip to content

fix(output): forward ByteBuffer error to queued command output (#3960) - #3963

Merged
a-TODO-rov merged 3 commits into
redis:mainfrom
ronitgupta138:fix/multioutput-error-tolerant-bytebuffer
Oct 21, 2026
Merged

a-TODO-rov merged 3 commits into
redis:mainfrom
ronitgupta138:fix/multioutput-error-tolerant-bytebuffer

Conversation

@ronitgupta138

@ronitgupta138 ronitgupta138 commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Problem

In transactions (MULTI/EXEC), MultiOutput.setError(ByteBuffer) previously decoded server errors to String before passing them to the currently decoded command output via setError(String).

Commands returning per-element errors (e.g. BF.MADD, BF.INSERT, CF.INSERTNX, TOPK.ADD, TOPK.INCRBY) use error-tolerant outputs (such as ErrorTolerantBooleanListOutput) which override setError(ByteBuffer) to record individual item failures as null in the result list. Because setError(String) was invoked by MultiOutput, the base CommandOutput implementation was triggered, erroneously failing the entire command with a RedisCommandExecutionException even though Redis applied the other elements.

Solution

Forward the raw ByteBuffer directly via queue.peek().getOutput().setError(error). Standard CommandOutput subclasses that do not override setError(ByteBuffer) preserve identical behavior by decoding the buffer in the base class.

Added unit test shouldForwardByteBufferErrorToErrorTolerantOutput in MultiOutputUnitTests.

Fixes #3960.


Note

Medium Risk
Touches transaction reply decoding in a core protocol path; behavior change is narrow but affects how errors propagate for commands inside EXEC.

Overview
Fixes EXEC transaction decoding so per-element Redis errors inside a command reply are handled by the command’s own output instead of failing the whole command.

MultiOutput.setError(ByteBuffer) now passes the raw buffer to the queued command output (setError(error)), rather than decoding it to a String first. That lets error-tolerant list outputs (e.g. for BF.MADD-style mixed success/error arrays) record failures as null or empty Value entries while the transaction and command still complete successfully.

Adds unit tests that simulate a MULTI/EXEC reply with one success and one ByteBuffer error for both ErrorTolerantBooleanListOutput and ErrorTolerantBooleanValueListOutput.

Reviewed by Cursor Bugbot for commit 0b2b8c2. Bugbot is set up for automated code reviews on this repo. Configure here.

Copilot AI balanced review requested due to automatic review settings October 20, 2026 19:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T11:05:07.481896Z 0b2b8c2 New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

ronitgupta138 added a commit to ronitgupta138/ronitgupta138 that referenced this pull request Oct 20, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a38943b64e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

MultiOutput<String, String> output = new MultiOutput<>(StringCodec.UTF8);
ErrorTolerantBooleanValueListOutput<String, String> errorTolerantOutput = new ErrorTolerantBooleanValueListOutput<>(
StringCodec.UTF8);
Command<String, String, List<io.lettuce.core.Value<Boolean>>> command = new Command<>(CommandType.BF_MADD,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Import Value instead of qualifying it inline

In the newly added value-output test, io.lettuce.core.Value is written inline here and again in the assertions despite there being no same-named type to disambiguate. Add an io.lettuce.core.Value import and use the simple Value name so the test follows the repository's required Java import convention.

AGENTS.md reference: AGENTS.md:L154-L156

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

Reviewed by Cursor Bugbot for commit dfd59eb. Configure here.


assertThat(result.wasDiscarded()).isFalse();
assertThat(result.<List<Boolean>> get(0)).containsExactly(true, null);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transaction test breaks inherited overloads

Medium Severity

The new bfMAddWithRejectedItemInTransaction test is inherited by cluster and reactive overloads that cannot run it as written. Cluster already disables MULTI tests because MULTI is unavailable, and reactive bfMAdd uses ErrorTolerantBooleanValueListOutput, so exec() returns List<Value<Boolean>> rather than List<Boolean> with raw nulls.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit dfd59eb. Configure here.

…#3960)

MultiOutput.setError(ByteBuffer) previously decoded the server error to
a String before passing it to the currently queued command output via
setError(String).

Commands returning per-element errors (e.g. BF.MADD, BF.INSERT, TOPK.ADD)
use error-tolerant outputs (such as ErrorTolerantBooleanListOutput) which
only override setError(ByteBuffer) to convert per-element failures into
null entries. Because setError(String) was called instead, the default
CommandOutput implementation was invoked, failing the entire command
and turning the TransactionResult entry into a RedisCommandExecutionException.

Pass the raw ByteBuffer directly to the queued command output via
setError(ByteBuffer). Standard CommandOutput instances that do not override
setError(ByteBuffer) retain their existing behavior by decoding the buffer
in the base class.

Signed-off-by: Ronit Gupta <[email protected]>
@ronitgupta138
ronitgupta138 force-pushed the fix/multioutput-error-tolerant-bytebuffer branch from dfd59eb to 0b2b8c2 Compare October 21, 2026 11:02
@a-TODO-rov
a-TODO-rov merged commit f38f2f8 into redis:main Oct 21, 2026
9 of 11 checks passed
ronitgupta138 added a commit to ronitgupta138/ronitgupta138 that referenced this pull request Oct 21, 2026
@a-TODO-rov a-TODO-rov mentioned this pull request Oct 22, 2026
4 tasks done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Error-tolerant outputs report a command failure inside MULTI/EXEC

3 participants