Skip to content

fix(grpcutil): resolve ambiguous code-only error mappings conservatively - #401

Open
ez-lbz wants to merge 3 commits into
a2aproject:mainfrom
ez-lbz:fix/grpc-error-reason-mapping
Open

fix(grpcutil): resolve ambiguous code-only error mappings conservatively#401
ez-lbz wants to merge 3 commits into
a2aproject:mainfrom
ez-lbz:fix/grpc-error-reason-mapping

Conversation

@ez-lbz

@ez-lbz ez-lbz commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What changed

1. Resolve ambiguous code-only gRPC error mappings conservatively

Problem:

When a gRPC status carries no ErrorInfo reason, FromGRPCError matched by code alone and picked the first mapping for that code. Several a2a errors share a gRPC code (e.g. FailedPrecondition maps to ErrTaskNotCancelable, ErrUnsupportedOperation, ...), so the picked error could be the wrong one.

Fix (internal/grpcutil/errors.go, internal/grpcutil/errors_test.go):

  • Collect every mapping whose code matches; use the single candidate when exactly one exists.
  • When multiple a2a errors share the code, fall back to the conservative a2a.ErrInternalError instead of guessing.
  • An explicit ErrorInfo reason still takes priority over the code-only fallback.
  • Added TestFromGRPCErrorCodeOnlyFallback and TestFromGRPCErrorReasonPriority.

Testing

  • go test ./internal/grpcutil/ ./a2agrpc/... ./a2aclient/... — all pass.
  • New tests cover single-candidate mapping (NotFound, Unimplemented, Canceled), ambiguous fallback (FailedPrecondition, InvalidArgument, Internal), and reason priority.

Behavior change: code-only errors for codes shared by several a2a errors now map to ErrInternalError instead of an arbitrary one; single-candidate and reason-based mappings are unchanged.

ez-lbz added 3 commits August 11, 2026 00:20
FromGRPCError falls back to code-only matching when a gRPC status has no
ErrorInfo reason. The old fallback took the first mapping matching the
code from the full table, which mis-maps codes shared by several a2a
errors (e.g. FailedPrecondition -> ErrTaskNotCancelable even when the
real error was ErrUnsupportedOperation or ErrExtendedCardNotConfigured).
When no reason is present, use the single mapping when exactly one error
exists for the code, otherwise fall back to the conservative
ErrInternalError instead of guessing. Reason-based matching is unchanged
and takes priority. Add regression tests for the fallback and for reason
priority.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant