Skip to content

[Bug]: v0.3 JSON-RPC compat adapter returns -32603 for all A2A errors (e.g. TaskNotFound should be -32001) #1368

Closed

Description

@shwetangsinha0509

What happened?

With create_jsonrpc_routes(..., enable_v0_3_compat=True), A2A errors raised while handling v0.3 JSON-RPC requests are returned as -32603 Internal error instead of their A2A error codes. The v1.0 dispatcher maps them correctly.

Request Expected Actual
v1.0 GetTask, unknown id -32001 -32001
v0.3 tasks/get, unknown id -32001 -32603
v0.3 tasks/cancel, unknown id -32001 -32603
v0.3 message/send with unknown taskId -32001 -32603
v0.3 tasks/resubscribe, streaming not supported -32004 -32603

A v0.3 client therefore cannot distinguish "task not found" from a server failure; the SDK's own v0.3 JsonRpcTransport maps the code back to InternalError instead of TaskNotFoundError.

Cause: in src/a2a/compat/v0_3/jsonrpc_adapter.py, A2AErrors from the request handler fall through to the generic except Exception in handle_request (and in the streaming event_generator), which wraps them in InternalError. JsonRpcDispatcher handles A2AError explicitly, and the v0.3 gRPC handler maps them via _ERROR_CODE_MAP.

Reproduction (main @ 261c074, also 1.2.2):

from starlette.applications import Starlette
from starlette.testclient import TestClient

from a2a.server.agent_execution import AgentExecutor
from a2a.server.request_handlers import DefaultRequestHandler
from a2a.server.routes import create_jsonrpc_routes
from a2a.server.tasks import InMemoryTaskStore
from a2a.types import AgentCapabilities, AgentCard


class NoopExecutor(AgentExecutor):
    async def execute(self, context, event_queue): ...
    async def cancel(self, context, event_queue): ...


card = AgentCard(name='t', description='t', version='1', capabilities=AgentCapabilities())
handler = DefaultRequestHandler(agent_executor=NoopExecutor(), task_store=InMemoryTaskStore(), agent_card=card)
app = Starlette(routes=create_jsonrpc_routes(request_handler=handler, rpc_url='/', enable_v0_3_compat=True))
client = TestClient(app)


def call(method, params, version):
    body = {'jsonrpc': '2.0', 'id': '1', 'method': method, 'params': params}
    return client.post('/', json=body, headers={'A2A-Version': version}).json()['error']['code']


print(call('GetTask', {'id': 'missing'}, '1.0'))    # -32001
print(call('tasks/get', {'id': 'missing'}, '0.3'))  # -32603, expected -32001

Expected: A2A errors keep their JSON-RPC codes on the v0.3 path. Errors that only exist in v1.0 (e.g. -32009 VersionNotSupported) should stay -32603, since v0.3 clients don't know those codes.

I have a fix with tests ready and will open a PR referencing this issue.

Relevant log output

-32001
   -32603

Code of Conduct

  • I agree to follow this project's Code of Conduct

Activity

  1. added
    component: serverIssues related to frameworks for agent execution, HTTP/event handling, database persistence logic.
    on Oct 22, 2026
  2. rohityan commented on Oct 22, 2026

    @rohityan

    Hi @shwetangsinha0509 , Thanks for the thorough report and fix. You correctly pinpointed the missing A2AErrorhandling in JSONRPCAdapter falling through to generic -32603 errors.
    Your fix in PR #1369 cleanly resolves the issue while respecting the v0.3 error code spec. Assigning this issue to you till your PR gets reviewed.

  3. shwetangsinha0509 commented on Oct 22, 2026

    @shwetangsinha0509
    Author

    Thanks @rohityan! Happy to make any changes needed on #1369.

  4. added a commit that references this issue on Oct 26, 2026
    8e32d53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

component: serverIssues related to frameworks for agent execution, HTTP/event handling, database persistence logic.status:awaiting response

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions