Skip to content

RATIS-2734. Fix NPE in RaftServerImpl.watchAsync for a write with a replication level - #1632

Open
smengcl wants to merge 1 commit into
apache:masterfrom
smengcl:RATIS-2734
Open

smengcl wants to merge 1 commit into
apache:masterfrom
smengcl:RATIS-2734

Conversation

@smengcl

@smengcl smengcl commented Oct 10, 2026

Copy link
Copy Markdown
Contributor

Generated-by: Claude Code (Opus 5.5)

What changes were proposed in this pull request?

A write sent with a replication level other than MAJORITY, for example client.async().send(message, ReplicationLevel.ALL_COMMITTED), never succeeds. After the write is applied, RaftServerImpl.waitForReplication builds an internal watch request without a message, and the dummy request check that RATIS-2497 added to RaftServerImpl.watchAsync calls request.getMessage().getContent() on it. The leader throws a NullPointerException, and the client keeps retrying according to its retry policy.

RaftServerImpl already has a null safe version of that check, isDummyRead, used on the read path. This change uses it in watchAsync as well and renames it to isDummy.

RaftAsyncTests.testWriteAsyncCustomReplicationLevel did not catch this because it never waited for the futures returned by send. The client was closed before any reply arrived, every future completed with AlreadyClosedException, and the callback only logged it. The test now waits for each reply and fails on an exception.

What is the link to the Apache JIRA

https://issues.apache.org/jira/browse/RATIS-2734

How was this patch tested?

testWriteAsyncCustomReplicationLevel with the stricter assertions fails without the fix and passes with it in TestRaftAsyncWithGrpc, TestRaftAsyncWithGrpcTracing and TestRaftAsyncWithNetty. TestLinearizableReadWithGrpc passes with the renamed check.

🤖 Generated with Claude Code

…eplication level

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@smengcl
smengcl marked this pull request as ready for review October 10, 2026 05:03
Copilot AI balanced review requested due to automatic review settings October 10, 2026 05:03

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.

🟢 Approval recommended

The focused fix addresses the NPE and the updated test reliably exercises the affected path.

0 open findings

What changed in this PR

Fixes the null-message NPE in custom-replication writes and strengthens regression coverage.

Changes:

  • Reuses the null-safe dummy-request check in watch and read paths.
  • Waits for and validates every asynchronous test reply.
File Description
RaftServerImpl.java Safely handles internal watch requests without messages.
RaftAsyncTests.java Ensures custom-replication writes complete successfully.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@amaliujia amaliujia 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.

Thanks!

futures.add(client.async().send(new SimpleMessage(s), ReplicationLevel.ALL_COMMITTED));
}
for (CompletableFuture<RaftClientReply> f : futures) {
final RaftClientReply reply = getWithDefaultTimeout(f);

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.

        if (exception != null) {
            LOG.error("Failed to send message " + s, exception);
            // reply should be null in case of exception
            Assertions.assertNull(reply);
            return;
          }

This code has been dropped. Is it because the NPE is gone?

@szetszwo

Copy link
Copy Markdown
Contributor

@smengcl , thanks for working on this! We need to update it for RATIS-2724. Otherwise, the change looks good.

This branch has not been deployed

No deployments
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.

4 participants