Skip to content

fix: return UnsupportedOperationError when subscribing to terminal tasks#784

Open
kabir wants to merge 2 commits intoa2aproject:mainfrom
kabir:issue-767
Open

fix: return UnsupportedOperationError when subscribing to terminal tasks#784
kabir wants to merge 2 commits intoa2aproject:mainfrom
kabir:issue-767

Conversation

@kabir
Copy link
Copy Markdown
Collaborator

@kabir kabir commented Apr 8, 2026

Per A2A spec, attempting to subscribe to a task in a terminal state (completed, failed, canceled, rejected) must return UnsupportedOperationError.

The issue had two parts:

  1. DefaultRequestHandler checked terminal state AFTER queue operations began, causing errors to be delivered via SSE stream instead of immediately.

  2. For streaming endpoints (subscribeToTask), immediate errors must be wrapped in SSE format so the client's SSE parser can process them and deliver to the error handler callback. Previously they were sent as plain JSON/HTTP responses which the SSE parser couldn't handle.

Changes:

  • Move terminal state validation BEFORE queue operations in DefaultRequestHandler
  • Wrap all immediate errors in SSE format for JSON-RPC routing layer
  • Wrap all immediate errors in SSE format for REST transport
  • Add integration test to verify fix across all three transports

Applied to HTTP+JSON, JSON-RPC, and gRPC transports.

Fixes #767

Per A2A spec, attempting to subscribe to a task in a terminal state
(completed, failed, canceled, rejected) must return UnsupportedOperationError.

The issue had two parts:

1. DefaultRequestHandler checked terminal state AFTER queue operations began,
   causing errors to be delivered via SSE stream instead of immediately.

2. For streaming endpoints (subscribeToTask), immediate errors must be wrapped
   in SSE format so the client's SSE parser can process them and deliver to
   the error handler callback. Previously they were sent as plain JSON/HTTP
   responses which the SSE parser couldn't handle.

Changes:
- Move terminal state validation BEFORE queue operations in DefaultRequestHandler
- Wrap all immediate errors in SSE format for JSON-RPC routing layer
- Wrap all immediate errors in SSE format for REST transport
- Add integration test to verify fix across all three transports

Applied to HTTP+JSON, JSON-RPC, and gRPC transports.

Fixes a2aproject#767

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves error handling for streaming requests by ensuring that attempts to subscribe to tasks in terminal states result in an UnsupportedOperationError, as per the A2A specification. The changes include updates to the routing and handler layers to correctly propagate these errors as SSE events or JSON-RPC error responses, along with a new test case to verify the behavior. A review comment suggests using String.format() for error messages in DefaultRequestHandler.java to improve code consistency.

…ultRequestHandler.java

Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
} catch (A2AError e) {
return ZeroPublisher.fromItems(new SendStreamingMessageResponse(request.getId(), e));
// Let routing layer catch TaskNotFoundError and UnsupportedOperationError to wrap in SSE format
throw e;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Maybe this is a bit agressive if there is an internal error or something else

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.

[Bug]: SubscribeToTask on terminal task returns TaskNotFoundError instead of UnsupportedOperationError

2 participants