a2aproject / a2aproject/a2a-python

[Bug]: grpc_handler maps 3 A2A errors to FAILED_PRECONDITION instead of UNIMPLEMENTED, and doesn't validate A2A-Version at all

未关闭
#1,166 4 条评论 0 个 reaction 已指派 1 人 已被 @avilleroy51 认领 在 GitHub 查看
component: server status:awaiting response status:stale
主要语言
Python
星标
2.1k
派生
496
平均合并
4 天 17 小时
30 天内合并 PR
12

描述

### What happened?

`grpc_handler.py`'s `_ERROR_CODE_MAP` (`src/a2a/server/request_handlers/grpc_handler.py:84-98`) maps 3 of the 9 A2A error types to the wrong gRPC status code, diverging from the canonical binding table in the spec (`specification.md` "Custom Binding Requirements" / error-code-mappings section):

| A2A Error Type | Spec gRPC Status | SDK gRPC Status |
|---|---|---|
| `PushNotificationNotSupportedError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` ❌ |
| `UnsupportedOperationError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` ❌ |
| `VersionNotSupportedError` | `UNIMPLEMENTED` | `FAILED_PRECONDITION` ❌ |

```python
_ERROR_CODE_MAP: dict[type[A2AError], grpc.StatusCode] = {
...
types.PushNotificationNotSupportedError: grpc.StatusCode.FAILED_PRECONDITION,
types.UnsupportedOperationError: grpc.StatusCode.FAILED_PRECONDITION,
...
types.VersionNotSupportedError: grpc.StatusCode.FAILED_PRECONDITION,
}
```

The other 6 mappings (`TaskNotFoundError`, `TaskNotCancelableError`, `ContentTypeNotSupportedError`, `InvalidAgentResponseError`, `ExtendedAgentCardNotConfiguredError`, `ExtensionSupportRequiredError`) are all correct against the same table.

### Second, related bug: gRPC transport doesn't validate `A2A-Version` at all

`jsonrpc_dispatcher.py` and `rest_dispatcher.py` both guard their handlers with `@validate_version(constants.PROTOCOL_VERSION_1_0)`, which raises `VersionNotSupportedError` for an unsupported `A2A-Version`. `grpc_handler.py` has no equivalent — a `SendMessage` gRPC call with metadata `a2a-version: 99.0` is processed normally instead of being rejected. Per spec (`specification.md:739`): "*Agents MUST process requests using the semantics of the requested `A2A-Version`... If the version is not supported by the interface, agents MUST return a `VersionNotSupportedError`.*"

### Reproduction

Against a standard `DefaultRequestHandlerV2`-backed gRPC server:

```python
import grpc
metadata = [("a2a-version", "99.0")]
client.stub.SendMessage(proto_request, metadata=metadata)
# succeeds — no VersionNotSupportedError, no version check at all
```

For the status-code mismatch, trigger any `PushNotificationNotSupportedError` (e.g. call `CreatePushNotificationConfig` when `capabilities.push_notifications` is `false`) over gRPC and inspect `e.code()` — it's `FAILED_PRECONDITION`, not `UNIMPLEMENTED`.

We hit both while running the official `a2a-tck` MUST-level gRPC suite against a reference SUT built on this SDK — `GRPC-ERR-002` fails on `test_push_not_supported_returns_unimplemented` and `test_version_not_supported_returns_unimplemented` for exactly these reasons.

### Expected

- Fix the 3 entries in `_ERROR_CODE_MAP` to `UNIMPLEMENTED`, matching the other 6 and the spec table.
- Apply the same version-validation the HTTP dispatchers already do to the gRPC transport (a `@validate_version`-equivalent, or an explicit check in `GrpcHandler` reading the `a2a-version` metadata key).

Happy to send a PR for both if useful.

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。