feat: Error recovery classification and standard error vocabulary#1083
Open
KonstantinMirin wants to merge 6 commits intoprebid:mainfrom
Open
feat: Error recovery classification and standard error vocabulary#1083KonstantinMirin wants to merge 6 commits intoprebid:mainfrom
KonstantinMirin wants to merge 6 commits intoprebid:mainfrom
Conversation
… AdCPError hierarchy Implements GH prebid#1072 — each AdCPError subclass now carries a recovery hint that helps buyer agents decide whether to retry, fix, or abandon a request. Defaults: ValidationError=correctable, RateLimitError=transient, AdapterError=transient, all others=terminal. Per-instance override via recovery= kwarg. to_dict() includes recovery in serialized output.
Rename RATE_LIMIT_EXCEEDED to RATE_LIMITED per AdCP spec. Add four new exception subclasses: AdCPConflictError (409), AdCPGoneError (410), AdCPBudgetExhaustedError (422), AdCPServiceUnavailableError (503). Update A2A error mapping and transport boundary translation for all new types. All error codes now use consistent UPPER_SNAKE_CASE.
…undaries MCP: ToolError now carries recovery as args[2], extract_error_info returns 3-tuple (code, message, recovery). A2A: _adcp_to_a2a_error forwards recovery in the JSON-RPC data field. REST: adcp_error_handler already used to_dict() which includes recovery; _handle_tool_error in api_v1.py now also extracts and forwards recovery. Tests: 31 assertions across all 3 transports verify recovery propagation.
…sses Cover recovery propagation through all 3 transport boundaries (MCP, A2A, REST): - to_dict() includes recovery for all 11 subclasses - Custom recovery= override preserved through MCP, A2A, and REST boundaries - Roundtrip tests: raise -> boundary catch -> serialize -> deserialize -> verify - Parametrized tests for all subclasses in both MCP and A2A transports - Integration tests for recovery in A2A ServerError.data and REST JSON body beads: salesagent-ezem
Review all ~87 raise AdCPError sites and add explicit recovery= overrides where the subclass default is wrong: - AdCPValidationError (default correctable) overridden to terminal for server data integrity errors (missing pricing_options, missing rate on fixed pricing, internal bugs, unimplemented features, missing identity) - AdCPValidationError overridden to transient for setup-incomplete and property-list-resolver failures (external service dependency) - AdCPNotFoundError (default terminal) overridden to correctable for format-not-found, creative-IDs-not-found, and package-not-found (buyer can fix their request and retry) - AdCPAdapterError (default transient) overridden to terminal for workflow context creation failure (internal DB, not external adapter) - AdCPAuthorizationError (default terminal) overridden to correctable for brand-manifest-required (buyer can add brand parameter) Also updates structural guard allowlist for line shift in products.py.
Cross-referenced our error_code strings against the canonical vocabulary in adcp-req ERROR_CODE_VOCABULARY.md. Found one mismatch: RATE_LIMITED should be RATE_LIMIT_EXCEEDED. Added vocabulary consistency guard test to prevent future divergence from the spec.
08287b2 to
96bdba5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds
RecoveryHintclassification (transient/correctable/terminal) to theAdCPError hierarchy and propagates it through all three transport boundaries (MCP, A2A, REST).
Buyer agents can now inspect the
recoveryfield in error responses to decide whether toretry, fix their request, or abandon.
RecoveryHinttype andrecoveryfield toAdCPErrorbase classAdCPConflictError(409),AdCPGoneError(410),AdCPBudgetExhaustedError(422),AdCPServiceUnavailableError(503)RATE_LIMITED→RATE_LIMIT_EXCEEDED)recoverythrough MCP (ToolErrorargs), A2A (datafield), and REST (JSONResponse)src/— 13 overrides where the subclass default was wrongMotivation
Closes #1072. Partial progress on #1075 (idempotency key schema prep deferred — blocked on
adcp Python library shipping the field).
Without recovery hints, buyer agents have no machine-readable signal for whether an error is
worth retrying. A transient adapter failure and a permanent validation error both look the same.
This PR gives every error a classification so agents can self-heal.
Changes
Exception hierarchy (
src/core/exceptions.py)Transport propagation
ToolError(code, message, recovery)— recovery carried as 3rd positional argInvalidParamsError(message=..., data={"recovery": "..."})— recovery in data field{"error_code": "...", "message": "...", "recovery": "...", "details": ...}Raise site audit (13 overrides)
Where the subclass default was incorrect for the specific error context:
AdCPValidationError→terminal(server data integrity, not user-fixable)AdCPValidationError→transient(pending admin setup / external service)AdCPNotFoundError→correctable(user can fix reference and retry)AdCPAdapterError→terminal(internal DB failure, not external adapter)AdCPAuthorizationError→correctable(buyer can add missing brand param)AdCPValidationError→terminal(feature gap, not user error)Test plan
recovery=overrides tested through all 3 boundariesmake quality: 3294 passed, 0 failed./run_all_tests.sh: all 5 suites pass (unit, integration, integration_v2, e2e, ui)Related