Repository navigation
Conversation
CompatRestTransport only turned an error body into an A2A error when it
looked like {"type": "TaskNotFoundError", "message": ...}. The v0.3
REST routes in this SDK (create_rest_routes with enable_v0_3_compat)
answer with a google.rpc.Status body carrying an ErrorInfo reason, the
same as the v1.0 binding. So a missing task came back as
MethodNotFoundError and an uncancelable task as a bare A2AClientError,
while the v0.3 JSON-RPC client and the v1.0 REST client raise
TaskNotFoundError and TaskNotCancelableError for the same server.
Run the body through _parse_rest_error from the v1.0 REST transport
first, so every reason in A2A_REASON_TO_ERROR is mapped. The old
"type" lookup and the status code fallback are kept after it.
🧪 Code Coverage (vs
|
| Base | PR | Delta | |
|---|---|---|---|
| src/a2a/compat/v0_3/rest_transport.py | 95.63% | 95.76% | 🟢 +0.13% |
| Total | 93.40% | 93.40% | ⚪️ 0.00% |
Generated by coverage-comment.yml
1AbdullahButt
left a comment
Contributor
There was a problem hiding this comment.
Looks correct, but it needs a rebase. git merge-tree against main conflicts in tests/compat/v0_3/test_rest_transport.py, which six compat fixes have changed since the branch point (#1420 through #1458). The source file merges cleanly.
What I checked:
_parse_rest_errorreturnsNonefor every shape the old code handled. It returnsNoneunless the body has anerrordict with adetailslist holding anErrorInfowhosereasonis inA2A_REASON_TO_ERROR(client/transports/rest.py:62-91). A{"type": ..., "message": ...}body, a bare{"message": ...}from a 0.3.x server, or{}from a non-JSON body all fall through to the existingtypelookup and the 404/status fallback. So the existing tests for those shapes still apply.- The raised error isn't swallowed by the outer
except. The newraise mapped from esits inside thetrythat catches(json.JSONDecodeError, ValueError)(rest_transport.py:385on the branch). Every class inA2A_REASON_TO_ERRORderives fromA2AError(Exception)(utils/errors.py:18), notValueError, so the mapped error gets out. The existingtypebranch relies on the same thing. - The v0.3 server sends
google.rpc.Status.compat/v0_3/rest_adapter.py:71/81uses the sharedrest_error_handler/rest_stream_error_handler, and those build their body with_create_error_response. That's the body the new unit test copies. - Streaming is covered too.
_send_stream_requestpassesself._handle_http_errortosend_http_stream_request. The v0.3 adapter fetches the first item before it opens the SSE response (rest_adapter.py:98-109), so pre-stream errors come back as HTTP errors and take this path. The adapter never sends anevent: errorframe, so the compat client doesn't need thesse_error_handlerthat the v1.0RestTransportpasses. - It matches the v1.0 client:
RestTransport._handle_http_error(client/transports/rest.py:373-387) calls_parse_rest_errorwith the same arguments.
I didn't run the tests.
Reviewed with help from Claude Code.
This branch has not been deployed
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.
Description
The v0.3 REST client in the compat package did not recognize the error bodies that this SDK's own v0.3 REST routes send.
CompatRestTransport._handle_http_erroronly mapped a body shaped like{"type": "TaskNotFoundError", "message": ...}. The v0.3 routes mounted bycreate_rest_routes(..., enable_v0_3_compat=True)go through the samerest_error_handleras v1.0 and return agoogle.rpc.Statuswith anErrorInforeason, for exampleSo against one server with both v0.3 bindings enabled, the two clients disagreed.
After the change all three REST rows raise
TaskNotFoundError,TaskNotFoundErrorandTaskNotCancelableError, matching JSON-RPC.The fix passes the parsed body to
_parse_rest_errorfroma2a.client.transports.rest, which is what the v1.0RestTransportalready uses, and raises the mapped error when there is one. That covers every reason inA2A_REASON_TO_ERROR, not only the two task errors above. Against the same app,send_messagewith an unsupported content type now raisesContentTypeNotSupportedErrorandcreate_task_push_notification_configraisesPushNotificationNotSupportedErrorwhen push is not supported, where both used to be a bareA2AClientError: HTTP Error 400.The existing
typelookup and the 404 and generic status fallback stay in place after it. I could not find any server in this repo or in a2a-sdk 0.3.26 that sends thetypeshape, but it is cheap to keep and an existing test covers it. A real 0.3.x Python server answers with{"message": ...}and no reason, so against that server a missing task still comes back asMethodNotFoundError. That is unchanged here and would need its own fix.Tests added in
tests/compat/v0_3/test_rest_transport.py. One is a parametrized unit test with the exact bodies the server produces forTASK_NOT_FOUND(404) andTASK_NOT_CANCELABLE(400). The other runsCompatRestTransportagainst a Starlette app built withcreate_rest_routes(enable_v0_3_compat=True)overhttpx.ASGITransport, parametrized over get on a missing task, cancel on a missing task and cancel on a completed one.With the source change reverted,
uv run pytest tests/compat/v0_3/test_rest_transport.pygives 5 failed, 32 passed (the new cases getMethodNotFoundErrorandA2AClientError: HTTP Error 400). With it, 37 passed. Fulluv run pytestis 2496 passed, 203 skipped, 4 xfailed, 1 xpassed../scripts/lint.shpasses, and--cov=srcputscompat/v0_3/rest_transport.pyat 96% with the new lines covered.CONTRIBUTINGGuide.bash scripts/format.shfrom the repository root to format)