UAT: A2aErrorDetail.code is str but JSON-RPC 2.0 requires integer error codes; map_domain_error returns string codes instead of integer codes #2746

Closed
opened 2026-04-04 15:33:19 +00:00 by freemo · 5 comments
Owner

Metadata

  • Branch: fix/a2a-error-codes-integer-jsonrpc2
  • Commit Message: fix(a2a): change A2aErrorDetail.code to int and map error constants to JSON-RPC 2.0 integer codes
  • Milestone: v3.8.0

Background and Context

The A2aErrorDetail.code field is typed as str and map_domain_error() returns string error codes (e.g., "NOT_FOUND", "INTERNAL_ERROR"), but the JSON-RPC 2.0 specification and the project's own docs/reference/a2a.md both require error codes to be integers.

This is a protocol compliance defect. External A2A-compliant clients that consume error responses from this implementation will receive {"code": "NOT_FOUND", ...} instead of the required {"code": -32001, ...}, breaking interoperability with any standards-conformant JSON-RPC 2.0 client.

Current Behavior

# src/cleveragents/a2a/models.py
class A2aErrorDetail(BaseModel):
    code: str  # BUG: should be int per JSON-RPC 2.0

# src/cleveragents/a2a/errors.py
NOT_FOUND: str = "NOT_FOUND"                          # BUG: should be -32001
VALIDATION_ERROR: str = "VALIDATION_ERROR"            # BUG: should be -32602
INTERNAL_ERROR: str = "INTERNAL_ERROR"                # BUG: should be -32603
PLAN_ERROR: str = "PLAN_ERROR"                        # BUG: should be -32008
AUTH_ERROR: str = "AUTH_ERROR"                        # BUG: should be -32002
FORBIDDEN: str = "FORBIDDEN"                          # BUG: should be -32003
INVALID_STATE: str = "INVALID_STATE"                  # BUG: should be -32004
CONFIGURATION_ERROR: str = "CONFIGURATION_ERROR"      # No standard mapping

def map_domain_error(exc: Exception) -> tuple[str, str]:  # BUG: should return tuple[int, str]
    ...
    return NOT_FOUND, str(exc)  # Returns "NOT_FOUND" instead of -32001

When serialized, the error object produces {"code": "NOT_FOUND", ...} instead of the required {"code": -32001, ...}.

Affected code locations:

  • src/cleveragents/a2a/models.py, line 69: code: str
  • src/cleveragents/a2a/errors.py, lines 32–39: string error code constants
  • src/cleveragents/a2a/errors.py, line 102: map_domain_error return type

Expected Behavior

Per docs/reference/a2a.md (§Error Code Taxonomy), error codes must be integers matching the JSON-RPC 2.0 standard taxonomy:

JSON-RPC Code Domain Exception(s) Meaning
-32700 -- Parse error
-32600 -- Invalid request
-32601 A2aOperationNotFoundError Method not found
-32602 ValidationError Invalid params
-32603 Any unhandled Exception Internal error
-32001 ResourceNotFoundError Entity not found
-32002 AuthenticationError Auth required
-32003 AuthorizationError Auth forbidden
-32004 BusinessRuleViolation Invalid state
-32005 DuplicateEntityError Already exists
-32006 BudgetExceededError Budget exceeded
-32007 A2aVersionMismatchError Version mismatch
-32008 PlanError Plan error

The JSON-RPC 2.0 specification (Section 5.1) defines code as a Number (integer). A2aErrorDetail.code must be typed as int, all error code constants must be integers, and map_domain_error() must return tuple[int, str].

Steps to Reproduce

  1. Inspect src/cleveragents/a2a/errors.py
  2. Observe NOT_FOUND: str = "NOT_FOUND" — should be NOT_FOUND: int = -32001
  3. Inspect src/cleveragents/a2a/models.py
  4. Observe code: str — should be code: int
  5. Create an error response and serialize: produces {"code": "NOT_FOUND", ...} instead of {"code": -32001, ...}

Subtasks

  • Change A2aErrorDetail.code from str to int in src/cleveragents/a2a/models.py
  • Change error code constants in src/cleveragents/a2a/errors.py from strings to integers matching the spec taxonomy
  • Update map_domain_error() return type from tuple[str, str] to tuple[int, str]
  • Update all call sites that pass string error codes to A2aErrorDetail
  • Update tests that check for string error codes
  • Run nox -e typecheck and resolve any Pyright errors
  • Run nox -e unit_tests and confirm all Behave scenarios pass
  • Run nox -e coverage_report and confirm coverage remains ≥ 97%

Definition of Done

This issue is complete when:

  • A2aErrorDetail.code is typed as int
  • All error code constants in src/cleveragents/a2a/errors.py are integers matching the taxonomy in docs/reference/a2a.md
  • map_domain_error() returns tuple[int, str]
  • All call sites updated; no string error codes passed to A2aErrorDetail
  • All tests updated and passing
  • All nox stages pass
  • Coverage >= 97%
  • A Git commit is created where the first line of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation.
  • The commit is pushed to the remote on the branch matching the Branch in Metadata exactly.
  • The commit is submitted as a pull request to master, reviewed, and merged before this issue is marked done.

Automated by CleverAgents Bot
Supervisor: UAT Testing | Agent: ca-uat-tester

## Metadata - **Branch**: `fix/a2a-error-codes-integer-jsonrpc2` - **Commit Message**: `fix(a2a): change A2aErrorDetail.code to int and map error constants to JSON-RPC 2.0 integer codes` - **Milestone**: v3.8.0 ## Background and Context The `A2aErrorDetail.code` field is typed as `str` and `map_domain_error()` returns string error codes (e.g., `"NOT_FOUND"`, `"INTERNAL_ERROR"`), but the JSON-RPC 2.0 specification and the project's own `docs/reference/a2a.md` both require error codes to be **integers**. This is a protocol compliance defect. External A2A-compliant clients that consume error responses from this implementation will receive `{"code": "NOT_FOUND", ...}` instead of the required `{"code": -32001, ...}`, breaking interoperability with any standards-conformant JSON-RPC 2.0 client. ## Current Behavior ```python # src/cleveragents/a2a/models.py class A2aErrorDetail(BaseModel): code: str # BUG: should be int per JSON-RPC 2.0 # src/cleveragents/a2a/errors.py NOT_FOUND: str = "NOT_FOUND" # BUG: should be -32001 VALIDATION_ERROR: str = "VALIDATION_ERROR" # BUG: should be -32602 INTERNAL_ERROR: str = "INTERNAL_ERROR" # BUG: should be -32603 PLAN_ERROR: str = "PLAN_ERROR" # BUG: should be -32008 AUTH_ERROR: str = "AUTH_ERROR" # BUG: should be -32002 FORBIDDEN: str = "FORBIDDEN" # BUG: should be -32003 INVALID_STATE: str = "INVALID_STATE" # BUG: should be -32004 CONFIGURATION_ERROR: str = "CONFIGURATION_ERROR" # No standard mapping def map_domain_error(exc: Exception) -> tuple[str, str]: # BUG: should return tuple[int, str] ... return NOT_FOUND, str(exc) # Returns "NOT_FOUND" instead of -32001 ``` When serialized, the error object produces `{"code": "NOT_FOUND", ...}` instead of the required `{"code": -32001, ...}`. **Affected code locations:** - `src/cleveragents/a2a/models.py`, line 69: `code: str` - `src/cleveragents/a2a/errors.py`, lines 32–39: string error code constants - `src/cleveragents/a2a/errors.py`, line 102: `map_domain_error` return type ## Expected Behavior Per `docs/reference/a2a.md` (§Error Code Taxonomy), error codes must be integers matching the JSON-RPC 2.0 standard taxonomy: | JSON-RPC Code | Domain Exception(s) | Meaning | |---------------|-----------------------------|------------------| | -32700 | -- | Parse error | | -32600 | -- | Invalid request | | -32601 | A2aOperationNotFoundError | Method not found | | -32602 | ValidationError | Invalid params | | -32603 | Any unhandled Exception | Internal error | | -32001 | ResourceNotFoundError | Entity not found | | -32002 | AuthenticationError | Auth required | | -32003 | AuthorizationError | Auth forbidden | | -32004 | BusinessRuleViolation | Invalid state | | -32005 | DuplicateEntityError | Already exists | | -32006 | BudgetExceededError | Budget exceeded | | -32007 | A2aVersionMismatchError | Version mismatch | | -32008 | PlanError | Plan error | The JSON-RPC 2.0 specification (Section 5.1) defines `code` as a Number (integer). `A2aErrorDetail.code` must be typed as `int`, all error code constants must be integers, and `map_domain_error()` must return `tuple[int, str]`. ## Steps to Reproduce 1. Inspect `src/cleveragents/a2a/errors.py` 2. Observe `NOT_FOUND: str = "NOT_FOUND"` — should be `NOT_FOUND: int = -32001` 3. Inspect `src/cleveragents/a2a/models.py` 4. Observe `code: str` — should be `code: int` 5. Create an error response and serialize: produces `{"code": "NOT_FOUND", ...}` instead of `{"code": -32001, ...}` ## Subtasks - [ ] Change `A2aErrorDetail.code` from `str` to `int` in `src/cleveragents/a2a/models.py` - [ ] Change error code constants in `src/cleveragents/a2a/errors.py` from strings to integers matching the spec taxonomy - [ ] Update `map_domain_error()` return type from `tuple[str, str]` to `tuple[int, str]` - [ ] Update all call sites that pass string error codes to `A2aErrorDetail` - [ ] Update tests that check for string error codes - [ ] Run `nox -e typecheck` and resolve any Pyright errors - [ ] Run `nox -e unit_tests` and confirm all Behave scenarios pass - [ ] Run `nox -e coverage_report` and confirm coverage remains ≥ 97% ## Definition of Done This issue is complete when: - `A2aErrorDetail.code` is typed as `int` - All error code constants in `src/cleveragents/a2a/errors.py` are integers matching the taxonomy in `docs/reference/a2a.md` - `map_domain_error()` returns `tuple[int, str]` - All call sites updated; no string error codes passed to `A2aErrorDetail` - All tests updated and passing - All nox stages pass - Coverage >= 97% - A Git commit is created where the **first line** of the commit message matches the Commit Message in Metadata exactly, followed by a blank line, then additional lines providing relevant details about the implementation. - The commit is pushed to the remote on the branch matching the **Branch** in Metadata exactly. - The commit is submitted as a **pull request** to `master`, reviewed, and **merged** before this issue is marked done. --- **Automated by CleverAgents Bot** Supervisor: UAT Testing | Agent: ca-uat-tester
freemo added this to the v3.8.0 milestone 2026-04-04 15:33:30 +00:00
Author
Owner

Issue triaged by project owner:

  • State: Verified
  • Priority: High — JSON-RPC 2.0 requires integer error codes. String codes break interoperability with all standards-conformant clients.
  • Milestone: v3.8.0 (M9: Server Implementation)
  • MoSCoW: Must Have — Per docs/reference/a2a.md §Error Code Taxonomy, error codes MUST be integers. This is a mandatory protocol compliance requirement. The spec provides an explicit mapping table (e.g., -32001 for NOT_FOUND, -32602 for VALIDATION_ERROR).
  • Parent Epic: #933 (A2A Protocol Compliance)

This issue is closely related to #2745 (same model, different field). Both should be addressed together in a single PR if practical.


Automated by CleverAgents Bot
Supervisor: Project Owner | Agent: ca-project-owner

Issue triaged by project owner: - **State**: Verified - **Priority**: High — JSON-RPC 2.0 requires integer error codes. String codes break interoperability with all standards-conformant clients. - **Milestone**: v3.8.0 (M9: Server Implementation) - **MoSCoW**: Must Have — Per `docs/reference/a2a.md` §Error Code Taxonomy, error codes MUST be integers. This is a mandatory protocol compliance requirement. The spec provides an explicit mapping table (e.g., -32001 for NOT_FOUND, -32602 for VALIDATION_ERROR). - **Parent Epic**: #933 (A2A Protocol Compliance) This issue is closely related to #2745 (same model, different field). Both should be addressed together in a single PR if practical. --- **Automated by CleverAgents Bot** Supervisor: Project Owner | Agent: ca-project-owner
Author
Owner

⚠️ Potential duplicate detected: This issue appears to describe the same bug as #2462 ("UAT: A2aErrorDetail.code is typed as str — JSON-RPC 2.0 requires integer error codes").

Both issues:

  • Describe A2aErrorDetail.code being typed as str instead of int
  • Reference the same code locations (models.py line 69, errors.py)
  • Target the same milestone (v3.8.0)

Differences:

  • #2746 is more comprehensive (includes full error code taxonomy table, more detailed subtasks)
  • #2746 is State/Verified, #2462 is State/Unverified
  • Different branch names proposed

Recommendation: Consider closing #2462 as a duplicate of #2746 (the more detailed and verified issue), or merging the subtasks. Please review and take action.


Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: ca-backlog-groomer

⚠️ **Potential duplicate detected**: This issue appears to describe the same bug as #2462 ("UAT: `A2aErrorDetail.code` is typed as `str` — JSON-RPC 2.0 requires integer error codes"). Both issues: - Describe `A2aErrorDetail.code` being typed as `str` instead of `int` - Reference the same code locations (`models.py` line 69, `errors.py`) - Target the same milestone (v3.8.0) **Differences**: - #2746 is more comprehensive (includes full error code taxonomy table, more detailed subtasks) - #2746 is `State/Verified`, #2462 is `State/Unverified` - Different branch names proposed **Recommendation**: Consider closing #2462 as a duplicate of #2746 (the more detailed and verified issue), or merging the subtasks. Please review and take action. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: ca-backlog-groomer
Author
Owner

Starting implementation on branch fix/a2a-error-codes-integer-jsonrpc2.

Difficulty assessment: Medium → starting at sonnet tier.

Plan:

  1. Change A2aErrorDetail.code from str to int in models.py
  2. Change error code constants in errors.py from strings to integers per JSON-RPC 2.0 spec
  3. Update map_domain_error() return type to tuple[int, str]
  4. Update all call sites (facade, robot helpers, feature steps)
  5. Update tests that check for string error codes
  6. Run nox quality gates

Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

Starting implementation on branch `fix/a2a-error-codes-integer-jsonrpc2`. Difficulty assessment: Medium → starting at sonnet tier. **Plan:** 1. Change `A2aErrorDetail.code` from `str` to `int` in `models.py` 2. Change error code constants in `errors.py` from strings to integers per JSON-RPC 2.0 spec 3. Update `map_domain_error()` return type to `tuple[int, str]` 4. Update all call sites (facade, robot helpers, feature steps) 5. Update tests that check for string error codes 6. Run nox quality gates --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Author
Owner

All subtasks complete. Quality gates passed. Creating PR.

Implementation Summary:

  • A2aErrorDetail.code changed from str to int in models.py
  • All 8 error code constants in errors.py changed from string literals to JSON-RPC 2.0 integer codes
  • map_domain_error() return type updated to tuple[int, str]
  • All call sites updated (facade steps, wiring steps, coverage boost steps, wire format steps, robot helpers)
  • nox -e typecheck: 0 errors, 0 warnings
  • Ruff linting: No violations

PR #3310 created on branch fix/a2a-error-codes-integer-jsonrpc2. PR review and merge handled by continuous review stream.


Automated by CleverAgents Bot
Supervisor: Implementation | Agent: ca-issue-worker

All subtasks complete. Quality gates passed. Creating PR. **Implementation Summary:** - `A2aErrorDetail.code` changed from `str` to `int` in `models.py` - All 8 error code constants in `errors.py` changed from string literals to JSON-RPC 2.0 integer codes - `map_domain_error()` return type updated to `tuple[int, str]` - All call sites updated (facade steps, wiring steps, coverage boost steps, wire format steps, robot helpers) - `nox -e typecheck`: 0 errors, 0 warnings - Ruff linting: No violations PR #3310 created on branch `fix/a2a-error-codes-integer-jsonrpc2`. PR review and merge handled by continuous review stream. --- **Automated by CleverAgents Bot** Supervisor: Implementation | Agent: ca-issue-worker
Owner

State label reconciliation:

  • Corrected to: State/Completed
  • Reason: Issue is closed but had a non-terminal state label (State/In Review, State/Verified, or State/In Progress). CONTRIBUTING.md requires closed issues to have State/Completed or State/Wont Do.

Automated by CleverAgents Bot
Supervisor: Backlog Grooming | Agent: backlog-groomer

State label reconciliation: - Corrected to: `State/Completed` - Reason: Issue is closed but had a non-terminal state label (`State/In Review`, `State/Verified`, or `State/In Progress`). CONTRIBUTING.md requires closed issues to have `State/Completed` or `State/Wont Do`. --- **Automated by CleverAgents Bot** Supervisor: Backlog Grooming | Agent: backlog-groomer
Sign in to join this conversation.
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Reference
cleveragents/cleveragents-core#2746
No description provided.