Skip to content

Client request handlers that complete empty send no JSON-RPC response #1124

Description

@1fanwang

Bug description

When a server sends a request to a Java SDK client, an asynchronous sampling or elicitation handler can return Mono.empty(). McpClientSession then sends no JSON-RPC response, so the server waits until its request timeout.

JSON-RPC 2.0 requires a response for every request with an ID. An empty handler completion should produce an error response with the original request ID.

This is the client-side counterpart to #1081. The open fix at #1099 changes only server-side dispatch paths.

Environment

  • Java SDK v2.0.1, commit c7e1cfe90edcd9cbe030924310a194dc5492eab2
  • Java SDK main, commit 39c225e46c51311eaf82192f15b950e421580fb5
  • Temurin 25.0.3, compiling with the repository's Java 17 target

Steps to reproduce

Register a client request handler that returns Mono.empty(), then deliver a JSON-RPC request with an ID:

var transport = new MockMcpClientTransport();
var session = new McpClientSession(TIMEOUT, transport,
		Map.of("test.method", params -> Mono.empty()), Map.of(), Function.identity());

transport.simulateIncomingMessage(new McpSchema.JSONRPCRequest("test.method", "test-id"));

assertThat(transport.getLastSentMessage()).isInstanceOf(McpSchema.JSONRPCResponse.class);

Both v2.0.1 and main fail because getLastSentMessage() is null:

Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
Expecting actual not to be null

Expected behavior

The client sends one JSON-RPC error response with ID test-id and code -32603.

Minimal Complete Reproducible example

The regression test is in McpClientSessionTests.testEmptyRequestHandlerSendsErrorResponse.

Activity

  1. ZYZ666-RGB commented on Sep 3, 2026

    @ZYZ666-RGB

    Hi, I'd like to work on this issue.

    I verified the behavior against the current main branch: when the client request handler returns Mono.empty(), handleIncomingRequest() completes without producing a JSONRPCResponse, so transport.sendMessage() is never invoked.

    I plan to:

    1. Add a focused regression test in McpClientSessionTests covering an empty request-handler completion.
    2. Verify that exactly one JSON-RPC error response is sent with the original request ID and INTERNAL_ERROR (-32603).
    3. Update the client request dispatch path so an empty completion becomes an explicit error response.
    4. Preserve the existing success, handler-error, and method-not-found behavior.

    I also checked #1099, which only covers the server-side dispatch path, so this would address the client-side counterpart described here.

    Could you please assign this issue to me if this approach looks good? Thank you!

  2. added
    bugSomething isn't working
    P2Moderate issues affecting some users, edge cases, potentially valuable feature
    on Sep 3, 2026
  3. added theissue type on Sep 3, 2026
  4. soyeladice-svg commented on Sep 26, 2026

    @soyeladice-svg

    Burs-IA / VECTOR would like to take a bounded reproduction + fix pass on this client-side JSON-RPC response gap, if maintainers are open to an external contribution.

    Proposed scope:

    1. reproduce the current-main failure where a client request handler completes with Mono.empty();
    2. pin the invariant that every JSON-RPC request with an id produces exactly one response;
    3. add a focused regression test around the existing client session path;
    4. implement the smallest fix that converts an unexpected empty completion into an explicit error response with the original id;
    5. verify that normal emitted results and exception/error paths are unchanged;
    6. run the repository's Maven test gates and keep the change limited to this client-side behavior.

    We will keep this separate from the analogous server-side issue so review stays focused.

    We understand the Java SDK contribution rules: AI-assisted work is acceptable only with accountable human review, and non-trivial changes should be clarified with maintainers before PR. We are therefore asking for scope confirmation before opening any PR.

    No production credentials, private data, or Burs-IA internals are involved.

  5. soyeladice-svg commented on Sep 26, 2026

    @soyeladice-svg

    Follow-up with concrete reproduction evidence from Burs-IA / DRIFT (BRS-00174), internally reviewed by VECTOR.

    Pinned upstream main:
    c7fef64f92a99c8c758b1aa634f92868d7c2963b

    Isolated public-source run:
    https://github.com/soyeladice-svg/-burs-ia-interop-lab./actions/runs/36216435482

    Observed:

    • current upstream + focused testEmptyRequestHandlerSendsErrorResponse: RED, 1 test / 1 failure;
    • candidate fix: add switchIfEmpty(...JSONRPCResponse.error(request.id(), INTERNAL_ERROR...));
    • focused regression after candidate fix: GREEN, 1/1;
    • existing McpClientSessionTests: GREEN, 12 tests / 0 failures / 0 errors / 0 skipped;
    • git diff --check: PASS.

    Sanitized receipt is now canonical in our private evidence repo; no Burs-IA Core, credentials, private data or production MCP endpoint was used.

    We have not opened an upstream PR and are not claiming acceptance. If the error shape/message above matches maintainer intent for the client-side counterpart of #1081, we can prepare the focused PR under the repository's contribution rules.

  6. 1fanwang commented on Sep 26, 2026

    @1fanwang
    Author

    I opened #1125 for this, with a regression test and the fix for the client-side empty-completion case.

  7. SiddhantShedge45 commented on Sep 30, 2026

    @SiddhantShedge45

    Hi maintainers, I’d like to work on this issue.

    I reviewed the reproduction involving Mono.empty() and the missing JSON-RPC response. I’d like to investigate the client request dispatch path, ensure an appropriate error response is generated when a handler completes empty, and add regression coverage for this behavior while preserving the existing success and error handling paths.

    If this issue is still available, I’d be happy to take it up and submit a PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Moderate issues affecting some users, edge cases, potentially valuable featurearea/clientbugSomething isn't working

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions