Affected version: a2a-sdk==1.0.1 with protobuf<6 (default ecosystem state at the time of release)
Status: Already fixed in 1.0.2 — filing for visibility, yank request, and to capture a clean repro.
Symptom
Every JSON-RPC message/send call to a server built on a2a-sdk==1.0.1 returns:
{
"jsonrpc": "2.0",
"id": "r1",
"error": {
"code": -32603,
"message": "'google._upb._message.FieldDescriptor' object has no attribute 'is_repeated'",
"data": null
}
}
Discovery (tools/list, /.well-known/agent-card.json) is unaffected — only mutating calls hit the validator.
Root cause
a2a-sdk==1.0.1 ships a validate_proto_required_fields decorator on RequestHandler.on_message_send:
# a2a/server/request_handlers/request_handler.py:284 (1.0.1)
async def async_wrapper(...):
if params is not None:
validate_proto_required_fields(params)
...
# a2a/utils/proto_utils.py:211 (1.0.1)
def _check_required_field_violation(msg, field):
if field.is_repeated: # ← attribute doesn't exist on _upb backend pre-protobuf-6
...
With protobuf<6 and the default C++ accelerated backend (google._upb._message.FieldDescriptor), is_repeated is not an attribute. It exists only on the pure-Python descriptor.FieldDescriptor.
a2a-sdk==1.0.2 reverted to the canonical, backend-agnostic check:
# a2a/utils/proto_utils.py:211 (1.0.2)
if field.label == FieldDescriptor.LABEL_REPEATED:
...
Minimal repro (no server)
from google.protobuf.descriptor import FieldDescriptor
from a2a.types_pb2 import SendMessageRequest
# 1.0.2 path — works on both backends
print("label-based:", any(f.label == FieldDescriptor.LABEL_REPEATED
for f in SendMessageRequest.DESCRIPTOR.fields))
# 1.0.1 path — fails on the default C++ backend with protobuf<6
for f in SendMessageRequest.DESCRIPTOR.fields:
print(f.name, f.is_repeated) # AttributeError on _upb.FieldDescriptor
End-to-end:
pip install 'a2a-sdk[http-server]==1.0.1' 'protobuf<6'
# ... start any A2A server ...
curl -X POST http://localhost:8080/ \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"message/send","id":"r1","params":{"message":{"role":"user","messageId":"m","kind":"message","parts":[{"kind":"data","data":{"skill":"any_skill","parameters":{}}}]}}}'
# → {"error":{"message":"'google._upb._message.FieldDescriptor' object has no attribute 'is_repeated'"}}
Adopter context
We hit this through adcp-client-python==4.4.0, which transitively pinned a2a-sdk<1.0.2,>=1.0.1 and didn't pin protobuf. That combination is broken end-to-end. adcp==4.4.1 switched to a2a-sdk<1.1,>=1.0.2 (pulling the upstream fix); adcp==4.4.2 reverted to <1.0.2,>=1.0.1 and instead pinned protobuf<8,>=6, working around the bug at the protobuf layer where _upb.FieldDescriptor.is_repeated does exist.
We're standardizing on the adcp 4.4.2 path — protobuf>=6 aligns with where the ecosystem is going. The bug in 1.0.1 is still worth mitigating because the protobuf>=6 pin isn't always inherited by adopters using a2a-sdk directly.
Asks
- Consider yanking
1.0.1 from PyPI — it's silently broken on the C++ protobuf backend without an explicit protobuf>=6 pin. 1.0.2 is fine; the yank just steers resolvers off the trap.
- If yanking isn't desirable, add an explicit
protobuf>=6 pin to 1.0.1's metadata (yank-and-replace) so the protobuf-side workaround is discoverable from pip install.
Affected version:
a2a-sdk==1.0.1withprotobuf<6(default ecosystem state at the time of release)Status: Already fixed in
1.0.2— filing for visibility, yank request, and to capture a clean repro.Symptom
Every JSON-RPC
message/sendcall to a server built ona2a-sdk==1.0.1returns:{ "jsonrpc": "2.0", "id": "r1", "error": { "code": -32603, "message": "'google._upb._message.FieldDescriptor' object has no attribute 'is_repeated'", "data": null } }Discovery (
tools/list,/.well-known/agent-card.json) is unaffected — only mutating calls hit the validator.Root cause
a2a-sdk==1.0.1ships avalidate_proto_required_fieldsdecorator onRequestHandler.on_message_send:With
protobuf<6and the default C++ accelerated backend (google._upb._message.FieldDescriptor),is_repeatedis not an attribute. It exists only on the pure-Pythondescriptor.FieldDescriptor.a2a-sdk==1.0.2reverted to the canonical, backend-agnostic check:Minimal repro (no server)
End-to-end:
Adopter context
We hit this through
adcp-client-python==4.4.0, which transitively pinneda2a-sdk<1.0.2,>=1.0.1and didn't pin protobuf. That combination is broken end-to-end.adcp==4.4.1switched toa2a-sdk<1.1,>=1.0.2(pulling the upstream fix);adcp==4.4.2reverted to<1.0.2,>=1.0.1and instead pinnedprotobuf<8,>=6, working around the bug at the protobuf layer where_upb.FieldDescriptor.is_repeateddoes exist.We're standardizing on the
adcp4.4.2 path —protobuf>=6aligns with where the ecosystem is going. The bug in 1.0.1 is still worth mitigating because theprotobuf>=6pin isn't always inherited by adopters usinga2a-sdkdirectly.Asks
1.0.1from PyPI — it's silently broken on the C++ protobuf backend without an explicitprotobuf>=6pin.1.0.2is fine; the yank just steers resolvers off the trap.protobuf>=6pin to1.0.1's metadata (yank-and-replace) so the protobuf-side workaround is discoverable frompip install.