Skip to main content
Version: 3.1.0

Errors and retries

Tell the agent what failed, where, and whether retrying can help. Skill errors use the same aap.error object across all three bindings. Transport and authentication errors keep their own protocol semantics.

One typed AAP error appears in MCP structured content, an A2A standard detail, or a PAP JSON bodyOpen full-size diagram

One automotive error​

{
"type": "aap.error",
"error_id": "error_example_001",
"code": "UNSUPPORTED_FILTER",
"message": "This deployment does not support features_all.",
"retryable": false,
"details": {
"errors": [
{ "instanceLocation": "/filters/features_all", "keyword": "capability", "error": "Filter is not advertised." }
],
"hint": "Read the published search capabilities before forming another query."
},
"created_at": "2026-10-24T15:00:00Z"
}

type, error_id, code, message, retryable and created_at are required. details is optional except where a code requires diagnostics or retry timing. Correlation IDs must be suitable for support without exposing shopper identity.

Validation errors MUST list every currently detectable problem in details.errors[]. Each item uses a JSON Pointer instanceLocation, a constraint keyword and a safe explanation in error. Never echo customer values, credentials or internal stack traces. Include a concrete correction when possible.

Three envelopes​

BindingSkill failure
MCPCompleted tool result, isError: true, typed error in structuredContent and matching serialized JSON text in content
A2AJSON-RPC error, standard ErrorInfo first in error.data[], typed error inside google.protobuf.Struct.value
PAP OpenAPIDirect aap.error JSON body with the mapped HTTP status

An unknown MCP tool, malformed protocol request, missing token, DPoP challenge or unsupported upstream version is a protocol failure. Do not pretend an automotive skill ran. MCP authorization discovery and PAP OAuth challenges are described in their binding pages.

A2A detail encoding​

For skill errors, the first google.rpc.ErrorInfo has reason equal to the AAP code and domain: "autoagentprotocol.org". Its string-valued metadata includes code, error_id, retryable and created_at. Duplicate the code in metadata for SDKs that omit reason.

The AAP payload is a separate standard Any detail with @type: "type.googleapis.com/google.protobuf.Struct" and value.type: "aap.error". Clients locate it by type, never by array position, validate its value, and ignore unrelated details. Other recognized detail objects may follow.

Complete A2A throttle response
{
"jsonrpc": "2.0",
"id": "req-rate-limited",
"error": {
"code": -32000,
"message": "Per-key rate limit exceeded.",
"data": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "RATE_LIMITED",
"domain": "autoagentprotocol.org",
"metadata": {
"code": "RATE_LIMITED",
"error_id": "err_01HZ9RATE01",
"retryable": "true",
"created_at": "2026-04-30T10:16:00Z"
}
},
{
"@type": "type.googleapis.com/google.protobuf.Struct",
"value": {
"type": "aap.error",
"error_id": "err_01HZ9RATE01",
"code": "RATE_LIMITED",
"message": "Per-key rate limit exceeded.",
"retryable": true,
"details": {
"retry_after_ms": 30000
},
"created_at": "2026-04-30T10:16:00Z"
}
}
]
}
}

Error code reference​

codeMeaningJSON-RPCretryable default
UNSUPPORTED_SKILLThe agent does not implement the skill identified by the typed request payload; the SendMessage method itself is supported.-32602 (Invalid params)false
UNSUPPORTED_FILTERA known filter or feature code is not supported in this deployment; nothing was silently ignored.-32602 (Invalid params)false
UNSUPPORTED_SORTThe requested sort field is not advertised.-32602 (Invalid params)false
INVALID_CURSORContinuation is expired, malformed, belongs to another scope, or no longer matches the request.-32602 (Invalid params)false
SCHEMA_VALIDATION_FAILEDRequest body fails JSON Schema validation.-32602 (Invalid params)false
MISSING_REQUIRED_FIELDA specifically required field is absent.-32602 (Invalid params)false
INVALID_CONDITIONvehicle_of_interest.condition is in the trade-in vocabulary, or trade_in.condition is in the sale-condition vocabulary.-32602 (Invalid params)false
DEALER_NOT_FOUNDThe requested seller is unknown or inaccessible on this endpoint.-32000 (Server error)false
VEHICLE_NOT_FOUNDThe supplied vin / stock / vehicle_id does not match any listing.-32000 (Server error)false
VEHICLE_UNAVAILABLEThe vehicle exists but its status is no longer one of available | intransit | pending.-32000 (Server error)false
CONTACT_CONSENT_REQUIREDconsent is missing from a lead submission.-32000 (Server error)false
INVALID_CONSENTconsent is present but malformed, expired, its scope does not cover the called skill, or a contact channel is not authorized.-32000 (Server error)false
APPOINTMENT_TIME_UNAVAILABLEThe submission was rejected because no appointment time could be accepted.-32000 (Server error)false
IDEMPOTENCY_CONFLICTAn idempotency_key was reused with a different request payload.-32000 (Server error)false
RATE_LIMITEDClient has exceeded the dealer's rate limit.-32000 (Server error)true
INTERNAL_ERRORUnhandled dealer-side error.-32603 (Internal error)true

These are the A2A numeric mappings. MCP keeps them as typed tool errors; PAP maps unsupported skill, unknown vehicle and unknown or inaccessible dealer (DEALER_NOT_FOUND) to 404, schema/filter/sort/cursor problems to 422, consent to 403, availability/appointment/idempotency conflict to 409, throttling to 429 and internal failure to 500.

Important distinctions​

  • UNSUPPORTED_FILTER means a known filter or feature code is unsupported here. An unknown field is SCHEMA_VALIDATION_FAILED. The server MUST NOT quietly ignore either.
  • INVALID_CURSOR means restart the search; never continue from a fabricated offset. A cursor is scoped to its original request, tenant and authorization context.
  • CONTACT_CONSENT_REQUIRED means the grant is missing. INVALID_CONSENT means the provided grant is unusable, expired, future-dated or does not permit the required channel.
  • VEHICLE_NOT_FOUND means no matching listing; VEHICLE_UNAVAILABLE means a previously known listing cannot be offered. Refresh the search and tell the buyer.
  • An accepted lead with a declined appointment returns lead.submit.response with both outcomes. APPOINTMENT_TIME_UNAVAILABLE must not conceal an accepted lead.
  • IDEMPOTENCY_CONFLICT means the same key was reused with different content. Do not rotate the key merely to overcome an uncertain previous write; first reconcile it.

Protocol-level A2A failures​

A2A errorJSON-RPCCause
ExtensionSupportRequiredError-32008The exact AAP extension was not activated.
VersionNotSupportedError-32009Supplied A2A-Version is unsupported; an explicitly empty value means 0.3. Omission on a contract-pinned AAP endpoint uses 1.0.
ContentTypeNotSupportedError-32005Unsupported input media type, or no acceptable output alternative.
UnsupportedOperationError-32004Unsupported A2A operation.
PushNotificationNotSupportedError-32003Push notification operations are not supported.

These use A2A's standard typed error.data array and need no aap.error. See headers and capabilities.

Activation recovery​

An activation error MUST name both the exact required extension URI and A2A-Extensions in its message. Its ErrorInfo uses domain: "a2a-protocol.org", reason: "EXTENSION_SUPPORT_REQUIRED" and matching string metadata extensionUri / requiredHeader. Those two metadata keys are AAP-defined recovery hints.

{
"jsonrpc": "2.0",
"id": "req-3",
"error": {
"code": -32008,
"message": "Activate the supported AAP profile with A2A-Extensions: https://autoagentprotocol.org/extensions/aap/v3.1",
"data": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "EXTENSION_SUPPORT_REQUIRED",
"domain": "a2a-protocol.org",
"metadata": {
"extensionUri": "https://autoagentprotocol.org/extensions/aap/v3.1",
"requiredHeader": "A2A-Extensions"
}
}
]
}
}

A buyer retries with that header only if it already implements the advertised contract. An error hint cannot implement the extension for the client. On a contract-pinned AAP endpoint, a missing header selects the configured contract; a supplied conflicting list still fails. The server MUST resolve and validate the contract before skill execution; an SDK import or card flag alone does not enforce it.

SDK error handling​

Preserve the raw protocol error before an SDK converts it. Extract and validate the typed AAP payload yourself; an exception class is not a retry policy.

The pinned @a2a-js/sdk 1.3.0 preserves the standard detail array in this repository's real HTTP interoperability checks. Some older client adapters discard unknown detail types or codes. Verify the exact client version you ship with validation, consent and rate-limit failures. MCP clients must preserve structured error results even though isError is true.

Retry without changing the outcome​

Honor the returned retryable value. For a correctable input error, change the request deliberately; repeating identical invalid input cannot help. For transient failures, use bounded backoff.

A typed RATE_LIMITED MUST include details.retry_after_ms; an HTTP 429 MUST include Retry-After. Wait at least the applicable minimum, including when Retry-After is an HTTP date. Do not treat an HTTP 200 containing an MCP tool error as success.

For a lead, preserve the original payload and idempotency key across a timeout, retry, Session renewal or securely correlated binding change. Re-authentication produces fresh proofs, not a new business request. A non-retryable response does not authorize a new submission. See safe lead retries.