Repository navigation
Answer an HTTP request whose reply cannot be generated with Internal error - #629
Merged
koic merged 1 commit intoOct 23, 2026
Conversation
…error ## Motivation and Context A response can hold a string that is not valid UTF-8 when the request carried one and the SDK or a handler repeated it, for example a tool name in its `Tool not found` error, since the JSON parser passes such bytes in a string value through. Generating that response raised `JSON::GeneratorError`. On the Streamable HTTP legacy path the error escaped while the SSE body was being written, cutting the response off; in JSON response mode and on the 2026-07-28 path the transport's rescue answered 500 with the error reported, for a failure that belongs to the one request. `JsonRpcHandler.handle_json` now answers such a request with `-32603` Internal error carrying the request id, and the 2026-07-28 path does the same before it writes the response. The error carries the request id when the response has one. In a batch each item that cannot be generated is replaced on its own, so the other items keep their results. The failure is passed to the exception reporter, since the Internal error sent to the client no longer shows what went wrong. Over stdio a batch is now answered by `handle_json` as well, with the request id, ahead of the transport's own fallback, which answered it without one. ## How Has This Been Tested? `test/json_rpc_handler_test.rb` and `test/mcp/server/transports/streamable_http_transport_test.rb` (the legacy SSE path, JSON response mode, and the 2026-07-28 path, each with a tool whose reply cannot be generated). Against the previous library the handler test raises `JSON::GeneratorError`, the SSE body raises it while it is written, and the other two answer 500. The handler test for a batch in which one item cannot be generated fails against the previous library, which has no `on_generate_error:`. The transport tests check that the failure reaches the exception reporter. The stdio batch test expects the item's id accordingly. ## Breaking Changes None.
atesgoral
approved these changes
Oct 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation and Context
A response can hold a string that is not valid UTF-8 when the request carried one and the SDK or a handler repeated it, for example a tool name in its
Tool not founderror, since the JSON parser passes such bytes in a string value through. Generating that response raisedJSON::GeneratorError. On the Streamable HTTP legacy path the error escaped while the SSE body was being written, cutting the response off; in JSON response mode and on the 2026-07-28 path the transport's rescue answered 500 with the error reported, for a failure that belongs to the one request.JsonRpcHandler.handle_jsonnow answers such a request with-32603Internal error carrying the request id, and the 2026-07-28 path does the same before it writes the response.The error carries the request id when the response has one. In a batch each item that cannot be generated is replaced on its own, so the other items keep their results. The failure is passed to the exception reporter, since the Internal error sent to the client no longer shows what went wrong. Over stdio a batch is now answered by
handle_jsonas well, with the request id, ahead of the transport's own fallback, which answered it without one.How Has This Been Tested?
test/json_rpc_handler_test.rbandtest/mcp/server/transports/streamable_http_transport_test.rb(the legacy SSE path, JSON response mode, and the 2026-07-28 path, each with a tool whose reply cannot be generated). Against the previous library the handler test raisesJSON::GeneratorError, the SSE body raises it while it is written, and the other two answer 500.The handler test for a batch in which one item cannot be generated fails against the previous library, which has no
on_generate_error:. The transport tests check that the failure reaches the exception reporter. The stdio batch test expects the item's id accordingly.Breaking Changes
None.
Types of changes
Checklist