fix: align REST message validation and SSE error format with JSON-RPC - #451
Open
ez-lbz wants to merge 2 commits into
Open
fix: align REST message validation and SSE error format with JSON-RPC#451ez-lbz wants to merge 2 commits into
ez-lbz wants to merge 2 commits into
Conversation
ez-lbz
force-pushed
the
fix/rest-validation-sse-errors
branch
from
August 11, 2026 13:38
0cea223 to
78955d6
Compare
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.
What changed
1. REST
message/sendandmessage:streamvalidate empty message partsProblem: The REST endpoints (
/message:send,/message:stream) bind the request with[FromBody], which does not validate thatMessage.Partsis non-empty. The JSON-RPC endpoint validates this inDeserializeAndValidateand rejects empty parts withInvalidParams. A REST client could send a message with no parts, which the server accepted — a REST/JSON-RPC validation gap.Fix (src/A2A.AspNetCore/A2AHttpProcessor.cs):
ValidateSendMessageRequestcalled at the start ofSendMessageRestAsyncandSendMessageStreamRest.Message.Partsnow throwsA2AException("Message parts cannot be empty", A2AErrorCode.InvalidParams), which the existing exception handling maps to HTTP 400 — identical behavior to the JSON-RPC binding.2. REST SSE error events use the structured JSON-RPC error shape
Problem: On a mid-stream error, the REST SSE writer (
A2AEventStreamResult) emitted a hardcodeddata: {"error":"An internal error occurred during streaming."}— losing the A2A error code, the exception message, and the structureddatadetails. The JSON-RPC SSE stream (JsonRpcStreamedResult) returns a fullcode/message/dataerror object. Clients switching between transports got inconsistent error handling.Fix (src/A2A.AspNetCore/A2AHttpProcessor.cs):
A2AEventStreamResultnow builds a structured error event:{"error":{"code":..,"message":..,"data":..}}viaBuildErrorJson.A2AExceptionerror codes are preserved (code= the A2A JSON-RPC error code, e.g.-32001); unexpected exceptions fall back to-32603(InternalError) with a generic message so internal details are never leaked.datacarries the samegoogle.rpc.ErrorInfoarray (@type,reason,domain) used by the JSON-RPC transport, so both transports produce consistent errors.Testing
dotnet test tests/A2A.AspNetCore.UnitTests --framework net8.0— 95 passed, 0 failed (baseline 88, +7 new regression tests: empty-parts rejection for REST send and streaming send with HTTP 400 + error message; SSE error code/message/data preservation forA2AException;-32603fallback without leaking generic exception messages; no error event on client disconnect; headers; valid data frames).dotnet test tests/A2A.UnitTests --framework net8.0— 420 passed, 0 failed (unchanged).code/message/datainstead of the hardcoded string. Clients parsing REST SSE errors should read the structurederrorobject; non-error stream frames are unchanged. RESTmessage/send/message:streamnow reject requests with empty message parts (HTTP 400) instead of accepting them.