[Bug]: §3.6 says patch versions do not affect protocol compatibility, but v1.0.1 changed six §5.4 transport mappings
- Dominant language
- Shell
- Stars
- 25.7k
- Forks
- 2.6k
- Avg merge
- 3d 6h
- Merged PRs (30d)
- 16
Description
### What happened?
## Summary
§3.6 (*Versioning*) says:
> Patch version numbers used by the specification, do not affect protocol
> compatibility. Patch version numbers SHOULD NOT be used in requests, responses
> and Agent Cards, and MUST not be considered when clients and servers negotiate
> protocol versions.
`v1.0.1` changed six of §5.4's nine error-mapping rows — HTTP statuses and gRPC
statuses, both observable on the wire:
| Error | v1.0.0 | v1.0.1 |
|---|---|---|
| `TaskNotCancelableError` | `409 Conflict` | `400 Bad Request` |
| `PushNotificationNotSupportedError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` |
| `UnsupportedOperationError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` |
| `ContentTypeNotSupportedError` | `415 Unsupported Media Type` | `400 Bad Request` |
| `InvalidAgentResponseError` | `502 Bad Gateway` | `500 Internal Server Error` |
| `VersionNotSupportedError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` |
A `v1.0.0`-conformant server answers `409` where a `v1.0.1`-conformant server
answers `400`. Both are "A2A 1.0", both are correct against the text they
implement, and §3.6 forbids the only mechanism that could tell them apart.
## This is not a request to revert the change
The change looks right and was made on purpose. `757f0ec`'s own message is
"Fix error code mappings table so that http codes correspond to
[`google.rpc.Code`](https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto)-defined
mappings", closing #1596, and it is listed in the `v1.0.1` release notes under
Bug Fixes. Aligning with `google.rpc.Code` is clearly the better table.
The report is about the interaction between that change and §3.6, and about how
an implementer is supposed to notice it.
## Why this is not theoretical
Two independent implementations read the `v1.0.0` table and had no signal that
it had moved:
* **`a2aproject/a2a-tck`**, the project's own conformance kit, still grades
§5.4 against `v1.0.0` — its `specification/version.json` pins that tag, and
the expectations in `tck/requirements/base.py` encode those values. Filed
separately as a2aproject/a2a-tck#231. It currently fails conformant servers
on five of the six rows.
* **`a2a-rust`** (mine) implemented the `v1.0.0` table until 2026-08-30. It was
found only by testing against an agent built on a different SDK and noticing
the two disagreed — not by reading anything.
Nothing in `docs/` records that the table changed or what it used to say; the
`v1.0.1` entry names the PR but not the wire effect, and a reader arriving at
"A2A 1.0" today has no way to tell which of the two tables another
implementation was built from.
## What would resolve it
Either of these would be enough; the second is smaller.
1. **Qualify §3.6.** If a patch release may correct transport-level mappings,
say so, and say how an implementation is expected to discover it — the
current text reads as a guarantee that nothing observable changes within a
`Major.Minor`, which is what made the drift invisible.
2. **Record the change where §5.4 is read.** A note under §5.4 (or in
`whats-new-v1.md`) saying the table was corrected in `v1.0.1`, listing the
prior values and pointing at #1627. That costs nothing and makes the
divergence self-diagnosing for anyone auditing an older implementation.
A third option, if the classification is the thing to fix rather than the text:
treat wire-observable corrections as warranting a `Minor` bump under §3.6's own
logic, so that the version an agent advertises continues to determine what it
answers.
## Related
* #1596 and #1627 — the issue and PR behind the change.
* a2aproject/a2a-tck#231 — the conformance kit still grading the `v1.0.0`
table. That one is a straightforward refresh; this one is why the refresh was
not obviously needed.
* #2184 — a separate §3.6.1 contradiction (header vs. request parameter). Not
the same defect, but the same section.
* #1925 — release cadence for `main`. Adjacent, since discoverability of
in-version changes is part of it.
*(Previously opened as #2199 against the wrong subject and closed; that issue
was the conformance-kit report, now correctly filed as a2aproject/a2a-tck#231.
This is the specification-side question that one raised.)*
### Relevant log output
```shell
# The clause
$ git clone -q https://github.com/a2aproject/A2A /tmp/A2A
$ git -C /tmp/A2A grep -n "MUST not be considered when clients and servers negotiate" main -- docs/specification.md
main:docs/specification.md:708:... Patch version numbers used by the specification, do not affect protocol
compatibility. Patch version numbers SHOULD NOT be used in requests, responses and
Agent Cards, and MUST not be considered when clients and servers negotiate protocol
versions.
# The same section heading in both releases
$ git -C /tmp/A2A show v1.0.0:docs/specification.md | grep -n "^### 3.6"
708:### 3.6 Versioning
# The table, v1.0.0 vs v1.0.1
$ for t in v1.0.0 v1.0.1; do
echo "-- $t"
git -C /tmp/A2A show $t:docs/specification.md \
| grep -E '^\| `(TaskNotCancelable|PushNotificationNotSupported|UnsupportedOperation|ContentTypeNotSupported|InvalidAgentResponse|VersionNotSupported)Error' \
| grep -E '\-32'
done
-- v1.0.0
| `TaskNotCancelableError` | `-32002` | `FAILED_PRECONDITION` | `409 Conflict` |
| `PushNotificationNotSupportedError` | `-32003` | `UNIMPLEMENTED` | `400 Bad Request` |
| `UnsupportedOperationError` | `-32004` | `UNIMPLEMENTED` | `400 Bad Request` |
| `ContentTypeNotSupportedError` | `-32005` | `INVALID_ARGUMENT` | `415 Unsupported Media Type` |
| `InvalidAgentResponseError` | `-32006` | `INTERNAL` | `502 Bad Gateway` |
| `VersionNotSupportedError` | `-32009` | `UNIMPLEMENTED` | `400 Bad Request` |
-- v1.0.1
| `TaskNotCancelableError` | `-32002` | `FAILED_PRECONDITION` | `400 Bad Request` |
| `PushNotificationNotSupportedError` | `-32003` | `FAILED_PRECONDITION` | `400 Bad Request` |
| `UnsupportedOperationError` | `-32004` | `FAILED_PRECONDITION` | `400 Bad Request` |
| `ContentTypeNotSupportedError` | `-32005` | `INVALID_ARGUMENT` | `400 Bad Request` |
| `InvalidAgentResponseError` | `-32006` | `INTERNAL` | `500 Internal Server Error` |
| `VersionNotSupportedError` | `-32009` | `FAILED_PRECONDITION` | `400 Bad Request` |
# Where the change landed
$ git -C /tmp/A2A log -1 --format='%cI %s' 757f0ec
2026-04-14T15:37:40-04:00 fix(spec): recent transcoding-related error changes (#1627)
$ for r in v1.0.0 v1.0.1 main; do
printf '%-8s ' "$r"
git -C /tmp/A2A merge-base --is-ancestor 757f0ec "$r" && echo has || echo lacks
done
v1.0.0 lacks
v1.0.1 has
main has
```
### Code of Conduct
- [x] I agree to follow this project's Code of Conduct
Contributor guide
Assessment
This issue has not been assessed yet.