{
  "schemaVersion": "1.0",
  "title": "Errors and retry decisions",
  "description": "AIP errors separate machine decisions from diagnostic text. Read the protocol code, category, retry hint, action or transaction state, and connector outcome evidence before deciding to correct, authorize, retry, reconcile, or stop.",
  "canonical": "https://getaip.org/docs/reference/errors",
  "route": "/docs/reference/errors",
  "source": "docs/reference/errors.md",
  "protocol": "Agent Interoperability Protocol",
  "protocolVersion": "1.0",
  "section": "API Reference",
  "documentType": "Reference",
  "language": "en",
  "revision": {
    "lastReviewedRevision": "d7cce13d1d555644d04a4d73c66c95b113737635",
    "documentationSourceRevision": "9192fef3695ad294994f2712f6d156241e5e92fb",
    "basis": "frontmatter"
  },
  "downloads": {
    "md": "/docs/download/reference/errors.md",
    "txt": "/docs/download/reference/errors.txt",
    "json": "/docs/download/reference/errors.json",
    "pdf": "/docs/download/reference/errors.pdf"
  },
  "content": {
    "format": "text/markdown",
    "markdown": "---\ntitle: Errors and retry decisions\ndescription: Interpret AIP and connector-fleet failures without causing duplicate effects\nkind: reference\naudience: developer\nappliesTo: \"1.x\"\nwritingStandard: \"aip-docs/1.0\"\nlastReviewedRevision: \"d7cce13d1d555644d04a4d73c66c95b113737635\"\n---\n\n# Errors and retry decisions\n\nAIP errors separate machine decisions from diagnostic text. Read the protocol\ncode, category, retry hint, action or transaction state, and connector outcome\nevidence before deciding to correct, authorize, retry, reconcile, or stop.\n\nThis reference describes source revision\n`d7cce13d1d555644d04a4d73c66c95b113737635`. It covers native AIP and the\nproduct-neutral connector fleet. Product-specific error codes and recovery\nprocedures belong to each of the six connector troubleshooting sections.\n\n## Protocol error object\n\n`ProtocolError` has three required fields and four optional fields:\n\n| Field | Required | Meaning |\n|---|---:|---|\n| `code` | Yes | Stable namespaced machine code |\n| `message` | Yes | Human-readable diagnostic summary |\n| `category` | Yes | One of the seven cross-implementation categories |\n| `retryable` | No | Explicit statement about retry safety for this failure |\n| `retry_after_ms` | No | Suggested delay before another eligible attempt |\n| `details` | No | Structured context whose shape belongs to the error producer |\n| `source` | No | Connector, profile, transport, or component metadata |\n\nOptional fields are omitted when absent; the Rust serializer does not emit\nthem as `null`. Automation should use `code`, `category`, and explicit retry\nstate. It must not match on `message` text.\n\n```json\n{\n  \"code\": \"idempotency.in_progress\",\n  \"message\": \"another execution owns this idempotency key\",\n  \"category\": \"temporary\",\n  \"retryable\": true,\n  \"retry_after_ms\": 1250,\n  \"details\": {\n    \"key\": \"booking-create-0190\",\n    \"owner_action_id\": \"act_0190c42f2d5a70008000000000000001\",\n    \"reservation_expires_at\": \"2026-07-26T12:00:01.25Z\"\n  },\n  \"source\": {\n    \"component\": \"aip-runtime\"\n  }\n}\n```\n\nThe protocol type permits arbitrary JSON in `details` and `source`. The typed\nconnector boundary requires redacted details, but consumers must not assume\nthat every producer enforced redaction. Apply authorization and logging policy\nbefore returning, retaining, or exporting either field.\n\n## Categories and native HTTP mapping\n\nThe native HTTP binding maps a protocol category to a recommended status:\n\n| Category | Native HTTP status | Meaning | Default operator decision |\n|---|---:|---|---|\n| `temporary` | 503 | The component may recover without changing the request | Retry only through an eligible retry policy |\n| `permanent` | 400 | The unchanged request cannot succeed | Correct input or stop |\n| `auth` | 401 | Authentication or authorization failed | Re-establish identity, tenant, scope, or trust; do not broaden authority automatically |\n| `policy` | 403 | An authenticated operation violates policy | Obtain the required decision or change the operation |\n| `economic` | 402 | Billing or settlement state prevents execution | Resolve account or settlement state before another attempt |\n| `connector` | 502 | Connector or downstream execution failed | Inspect connector evidence and outcome certainty |\n| `transport` | 503 | The delivery path failed | Recover delivery, then determine whether execution may already have started |\n\nThis mapping applies when an HTTP handler delegates status selection to the\nnative binding. A route may intentionally use a more specific status. For\nexample, connector-host capacity returns 429 and replay returns 409. Always\nparse the response body as well as the status.\n\n## Where an error appears\n\n### Native error envelope\n\nA message-level failure is carried in an envelope with message type\n`aip.core.v1.error` and `body.error.error` containing `ProtocolError`. Native\nHTTP returns that envelope with a mapped status. Native NATS returns the same\nerror envelope without an HTTP status.\n\nThe signed connector-host path correlates an error response to the request,\naddresses it to the request sender, and signs it. A client must verify the\nresponse signature and correlation before trusting the embedded error.\n\n### Failed action result\n\nA capability may return an `ActionResult` whose `status` is `failed` and whose\n`error` is a `ProtocolError`. The enclosing HTTP request can still succeed.\nInspect the action result instead of treating HTTP success as action success.\n\nAn acknowledgement can also reject or queue an action and carry `reason` and\n`retry_after_ms` without a `ProtocolError`. Treat those as acknowledgement\nstate, not as a substitute error object.\n\n### Compact HTTP error\n\nSome pre-envelope or ergonomic routes return a compact object under `error`.\nExamples include JSON decoding before an envelope exists and capability-catalog\ndiscovery. A compact error can omit category, retry fields, or source. Use the\nroute's documented status and code; do not synthesize missing retry authority.\n\n### Model Context Protocol mapping\n\nThe Model Context Protocol (MCP) profile maps AIP categories to JSON-RPC codes:\n\n| AIP category | JSON-RPC code |\n|---|---:|\n| `auth` | `-32001` |\n| `policy` | `-32003` |\n| `temporary`, `transport` | `-32010` |\n| `connector` | `-32020` |\n| `economic` | `-32030` |\n| `permanent` | `-32602` |\n\nWhen an AIP error has `details`, the current mapper uses those details directly\nas JSON-RPC `data`. When details are absent, `data` contains AIP extension\nmetadata with code, category, retry fields, and source. A generic MCP client\nmust therefore not assume that every projected failure exposes the AIP code.\n\n## Retry decision order\n\nApply these checks in order. A later `yes` cannot override an earlier stop.\n\n| Check | Continue only when | Otherwise |\n|---|---|---|\n| Outcome certainty | No side effect occurred, or the same effect can be reconciled safely | Read durable action or transaction state and reconcile |\n| Capability contract | `supports_retry` is true | Stop or follow the capability's recovery procedure |\n| Retry safety | Safety is `safe`, or `safe_with_idempotency_key` with a key present | Do not repeat the action |\n| Result state | The action result is `failed` | Follow the lifecycle for queued, pending, cancelled, or terminal success state |\n| Explicit error hint | `retryable` is not `false` | Stop; correct the cause instead |\n| Category fallback | `retryable` is `true`, or absent and the policy accepts the category | Stop unless a higher-level contract explicitly provides recovery |\n| Attempt and elapsed budget | Another bounded attempt fits both limits | Dead-letter, reconcile, or escalate |\n| Delay | Backoff and any retry hint fit the remaining budget | Stop or wait for a later operator decision |\n\nAt this revision, queued-runtime retry policy behaves as follows:\n\n- `safe` and `safe_with_idempotency_key` capabilities receive a maximum of\n  three attempts by default; `unsafe` and `unknown` receive one;\n- `safe_with_idempotency_key` cannot retry without an idempotency key;\n- `retryable: false` always stops the runtime retry;\n- `retryable: true` permits the error-hint gate, subject to every other gate;\n- absent `retryable` falls back to configured categories, whose default set is\n  `temporary`, `transport`, and `connector`;\n- `retry_after_ms` is clamped to at least 1 ms and at most the policy's maximum\n  backoff; absent delay uses bounded exponential backoff;\n- the retry is rejected if the next delay exceeds `max_elapsed_ms`.\n\nThese are current runtime defaults, not a protocol mandate for every AIP\nimplementation. A client should read durable status before resubmitting after\nan interrupted transport exchange.\n\n## Unknown outcomes\n\nA transport failure after dispatch does not prove that a provider mutation did\nnot happen. A typed `ConnectorFailure` carries the evidence needed to choose a\nsafe branch:\n\n| Connector field | Recovery use |\n|---|---|\n| `provider_request_id` | Correlate provider logs and support evidence |\n| `provider_operation` | Identify provider, operation ID, and optional request ID |\n| `remote_status` | Record the downstream protocol status |\n| `uncertain_outcome` | Prevent blind replay when an external effect may exist |\n| `operation` | Identify discovery, admission, invocation, cancellation, streaming, health, transaction, reconciliation, compensation, emission, or ingestion |\n| `redacted_details` | Retain bounded diagnostic evidence without raw provider data |\n| `source` | Identify the connector component that produced the failure |\n\nThe conversion to `ProtocolError` places these values in `details` and preserves\nthe connector's code, category, retry flag, and delay. Conversion in the other\ndirection treats absent `retryable` as false.\n\nFor transaction modes `commit` and `execute`, the runtime moves the transaction\ntoward `outcome_unknown` when the result has code `sla.timeout_exceeded` or\n`details.uncertain_outcome` is true. Use the captured provider operation ID and\nthe reconciliation action. Do not create a second mutation merely because a\ntransport or timeout category looks temporary.\n\n## Common native code families\n\nThe table lists product-neutral families implemented at the pinned revision.\nIt is a lookup aid, not an exhaustive registry of provider-specific codes.\n\n| Code or prefix | Typical meaning | Decision |\n|---|---|---|\n| `action.invalid_input` | Required action data or a semantic invariant is invalid | Correct the action; unchanged retry is false |\n| `capability.unsupported` | The endpoint or manifest does not own the requested capability or message | Rediscover capabilities or choose another endpoint |\n| `resource.not_found`, `receipt.not_found` | Selected session, capability, resource, or receipt is absent | Check the identifier and tenant boundary |\n| `handshake.no_compatible_profile` | No requested profile is supported | Negotiate a profile present in the manifest |\n| `auth.native_http_unauthorized` | Native bearer authentication is missing, invalid, or not configured for the presented token | Correct authentication; do not retry with broader scopes |\n| `auth.*`, `credential.*`, `audit.not_authorized` | Actor, claim, tenant, session, credential, ownership, or scope does not match trusted context | Re-establish the intended identity and authority |\n| `auth.signature.invalid`, `replay.message_id` | Signature verification or replay fencing failed | Stop; correct signing, clock, message identity, or replay state |\n| `query.invalid`, `query.invalid_cursor` | Query syntax or cursor format is invalid | Correct the query or restart pagination as documented |\n| `stream.cursor_expired` | Cursor is outside the retained replay window | Read current durable state, then restart from an available cursor |\n| `idempotency.in_progress` | Another action owns the scoped key until its reservation expires | Read the owning action; wait for the bounded retry delay |\n| `policy.human_approval_required` | Execution is pending an approval lifecycle decision | Submit or await approval; do not retry the action |\n| `sla.timeout_exceeded` | The handler exceeded its effective action timeout | Inspect cancellation and outcome certainty before any retry |\n| `sla.queue_delay_exceeded` | A queued action exceeded the capability's maximum queue delay | Stop or resubmit as a new authorized operation if appropriate |\n| `storage.unavailable` | Durable runtime storage failed | Retry only within policy; verify durable state before replay |\n| `runtime.handler_failed` | A handler was missing or returned an implementation failure | Diagnose ownership and implementation before relying on retry |\n| `manifest.admission_failed`, `implementation.*` | Manifest or handler ownership admission failed | Fix deployment admission; client retry cannot repair it |\n| `transaction.*` | Plan, commit, compensation, rollback, or reconciliation policy failed | Follow transaction state and its exact recovery branch |\n| `delegation.*` | Target, route, depth, identity, or policy rejected delegation | Correct the delegation contract or authority |\n\n## Connector-fleet runtime errors\n\n### Catalog and central admission\n\nThe tenant capability-catalog route uses compact HTTP errors:\n\n| Code | HTTP status | Decision |\n|---|---:|---|\n| `connector_catalog.disabled` | 404 | Configure the catalog; client retry cannot enable it |\n| `connector_catalog.tenant_required` | 403 | Bind the authenticated actor to a verified tenant |\n| `connector_catalog.invalid_query` | 400 | Correct capability, profile, cursor, text, or limit input |\n| `connector_catalog.stale_cursor` | 409 | Discard the cursor and restart at the first page |\n| `connector_catalog.unavailable` | 503 | Retry the read with bounded backoff |\n\nCentral remote routing and admission return structured protocol errors where\nthe condition has a stable client decision:\n\n| Code | Category and retry | Decision |\n|---|---|---|\n| `connector.request_rejected` | `permanent`, false | Correct invalid limits or oversized work |\n| `connector.scheduler_overloaded` | `temporary`, true, 100 ms | Retry only within tenant fairness and action retry policy |\n| `connector.admission_capacity` | `temporary`, true, bounded registry delay | Wait for the exhausted admission scope; do not bypass the quota |\n\nBinding absence, replica unavailability, stale registry state, fence loss, and\nstorage failures can surface through a broader runtime error when no dedicated\nprotocol mapping exists. Operators should inspect registry and fleet state\nrather than infer a specific code from generic handler text.\n\n### Connector-host execution\n\nAuthenticated host requests receive a signed error envelope for these\nconditions:\n\n| Code | HTTP | Category and retry | Decision |\n|---|---:|---|---|\n| `connector_host.not_ready` | 503 | `temporary`, true, heartbeat interval | Wait for a valid lease and ready non-draining host |\n| `connector_host.capacity` | 429 | `temporary`, true, 100 ms | Respect local concurrency; do not scale by bypassing admission |\n| `connector_host.approval_authorization_unavailable` | 503 | `temporary`, true, 1,000 ms | Recover the approval journal and retry within policy |\n| `connector_host.approval_authorization_conflict` | 403 | `auth`, false | Reconcile the signed approval with durable host state |\n| `connector_host.credential_revision_unavailable` | 503 | `temporary`, true, 1,000 ms | Restore credential-revision resolution without changing the pin |\n| `connector_host.credential_revision_denied` | 403 | `auth`, false | Correct tenant, instance, capability, or revision authorization |\n| `connector_host.route_mismatch` | 403 | `auth`, false | Discard the request and re-resolve the exact admitted route |\n| `connector_host.authentication` | 401 | `auth`, false | Correct gateway identity, DID, signature, or trust domain |\n| `connector_host.replay` | 409 | `policy`, false | Do not reuse the message ID; inspect prior execution state |\n| `connector_host.execution` | 502 | `connector`, false | Diagnose the host runtime or unsupported message before retry |\n\nSchema/decode failures and response-signing failures occur before a trustworthy\nsigned response can be produced. Those paths use compact unsigned JSON with\n400 or 500. Treat an unsigned failure as transport evidence only; never accept\nits body as authenticated host state.\n\n### Event and stream-callback ingress\n\n| Code | Category and retry | Decision |\n|---|---|---|\n| `connector_event.capacity` | `temporary`, true, 100 ms | Retry the same idempotent event envelope within ingress bounds |\n| `connector_event.invalid` | `permanent`, false | Correct envelope type, size, route, event, or chunk shape |\n| `connector_event.not_authorized` | `auth`, false | Correct recipient, signer, route assignment, tenant, or binding |\n| `connector_event.idempotency_conflict` | `permanent`, false | Stop: the event ID already owns different retained content |\n| `connector_event.unavailable` | `temporary`, true, 1,000 ms | Recover registry or durable event state before bounded retry |\n| `connector_event.not_configured` | `permanent`, false | Configure central ingress before sending callbacks |\n\n## Registry and admission operator failures\n\nRegistry and admission CLI commands fail through standard error and non-zero\nexit status. Their Rust error families are not `ProtocolError` codes and do not\ncarry a wire-level retry flag.\n\n| Failure family | Meaning | Operator action |\n|---|---|---|\n| Admission `Invalid` | Package, policy, identity, limit, or invariant is invalid | Correct the document; do not retry unchanged |\n| Admission `Signature` | Package or evidence signature cannot be verified | Stop and correct the signer, DID, signature, or canonical object |\n| Admission `Evidence` | Required evidence is missing, stale, mismatched, revoked, or rejected | Replace or regenerate the exact evidence set |\n| Admission `Registry` | Applying the verified package failed in catalog storage | Read the durable admission operation before safely resuming |\n| Admission `Journal` | The durable operator journal failed | Restore journal authority and inspect partial state |\n| Admission `Conflict` | Package identity, revision, digest, or terminal revoke conflicts | Reconcile the exact recorded operation; never overwrite it |\n| Registry `BindingUnavailable` | No enabled tenant binding owns the capability | Correct or enable the admitted binding |\n| Registry `ReplicaUnavailable` | No ready replica has capacity | Restore host lease/readiness or scale through admitted orchestration |\n| Registry `CapacityExceeded` | A hard admission counter reached its limit | Respect its bounded retry delay or change approved capacity |\n| Registry `StaleCursor` | Catalog revision changed during pagination | Restart the catalog query from the first page |\n| Registry `FenceLost` | Route assignment fencing failed | Discard the route and resolve a new fenced assignment |\n| Registry `Storage` | Durable registry access failed | Recover storage, then inspect the exact operation before retry |\n\nUse `connector registry plan` to verify without writing. `apply` journals and\nresumes an exact package revision and digest; `status` is the recovery source.\nDo not repeatedly invoke `apply` based only on an error string.\n\n## Callback and delivery failures\n\nAction execution, callback delivery, and event ingestion are separate durable\nboundaries. A completed action can coexist with a failed callback. Recover the\ncallback from its durable outbox or event state; do not rerun the provider\naction to compensate for delivery failure.\n\nLikewise, a successful transport response can contain a failed action result,\nand a failed transport exchange can leave an action running. Read action,\ntransaction, event, and receipt state before choosing another mutation.\n\n## Security and observability\n\n- Log code, category, action ID, transaction ID, correlation ID, retry decision,\n  attempt, and redacted source metadata.\n- Do not log credentials, raw provider bodies, bearer tokens, signing seeds, or\n  unreviewed details.\n- Keep one metric label set per bounded code family; do not label by free-form\n  message, tenant, provider request ID, or resource ID.\n- Treat signature, tenant, route, credential-revision, approval-conflict,\n  replay, and fence failures as security events, not ordinary availability.\n- Preserve durable receipts and provider operation references for an unknown\n  outcome or contested retry.\n\n## Related reference\n\n- [Native HTTP API](http-api.md)\n- [Connector fleet HTTP API](connector-fleet-api.md)\n- [Transport bindings](transport-bindings.md)\n- [`getaip` CLI](cli.md)\n- [Actions and sessions](../concepts/actions-and-sessions.md)\n",
    "text": "Errors and retry decisions\n\nAIP errors separate machine decisions from diagnostic text. Read the protocol\ncode, category, retry hint, action or transaction state, and connector outcome\nevidence before deciding to correct, authorize, retry, reconcile, or stop.\n\nThis reference describes source revision\nd7cce13d1d555644d04a4d73c66c95b113737635. It covers native AIP and the\nproduct-neutral connector fleet. Product-specific error codes and recovery\nprocedures belong to each of the six connector troubleshooting sections.\n\nProtocol error object\n\nProtocolError has three required fields and four optional fields:\n\n| Field | Required | Meaning |\n\n| code | Yes | Stable namespaced machine code |\n| message | Yes | Human-readable diagnostic summary |\n| category | Yes | One of the seven cross-implementation categories |\n| retryable | No | Explicit statement about retry safety for this failure |\n| retryafterms | No | Suggested delay before another eligible attempt |\n| details | No | Structured context whose shape belongs to the error producer |\n| source | No | Connector, profile, transport, or component metadata |\n\nOptional fields are omitted when absent; the Rust serializer does not emit\nthem as null. Automation should use code, category, and explicit retry\nstate. It must not match on message text.\n\n{\n  \"code\": \"idempotency.inprogress\",\n  \"message\": \"another execution owns this idempotency key\",\n  \"category\": \"temporary\",\n  \"retryable\": true,\n  \"retryafterms\": 1250,\n  \"details\": {\n    \"key\": \"booking-create-0190\",\n    \"owneractionid\": \"act0190c42f2d5a70008000000000000001\",\n    \"reservationexpiresat\": \"2026-07-26T12:00:01.25Z\"\n  },\n  \"source\": {\n    \"component\": \"aip-runtime\"\n  }\n}\n\nThe protocol type permits arbitrary JSON in details and source. The typed\nconnector boundary requires redacted details, but consumers must not assume\nthat every producer enforced redaction. Apply authorization and logging policy\nbefore returning, retaining, or exporting either field.\n\nCategories and native HTTP mapping\n\nThe native HTTP binding maps a protocol category to a recommended status:\n\n| Category | Native HTTP status | Meaning | Default operator decision |\n\n| temporary | 503 | The component may recover without changing the request | Retry only through an eligible retry policy |\n| permanent | 400 | The unchanged request cannot succeed | Correct input or stop |\n| auth | 401 | Authentication or authorization failed | Re-establish identity, tenant, scope, or trust; do not broaden authority automatically |\n| policy | 403 | An authenticated operation violates policy | Obtain the required decision or change the operation |\n| economic | 402 | Billing or settlement state prevents execution | Resolve account or settlement state before another attempt |\n| connector | 502 | Connector or downstream execution failed | Inspect connector evidence and outcome certainty |\n| transport | 503 | The delivery path failed | Recover delivery, then determine whether execution may already have started |\n\nThis mapping applies when an HTTP handler delegates status selection to the\nnative binding. A route may intentionally use a more specific status. For\nexample, connector-host capacity returns 429 and replay returns 409. Always\nparse the response body as well as the status.\n\nWhere an error appears\n\nNative error envelope\n\nA message-level failure is carried in an envelope with message type\naip.core.v1.error and body.error.error containing ProtocolError. Native\nHTTP returns that envelope with a mapped status. Native NATS returns the same\nerror envelope without an HTTP status.\n\nThe signed connector-host path correlates an error response to the request,\naddresses it to the request sender, and signs it. A client must verify the\nresponse signature and correlation before trusting the embedded error.\n\nFailed action result\n\nA capability may return an ActionResult whose status is failed and whose\nerror is a ProtocolError. The enclosing HTTP request can still succeed.\nInspect the action result instead of treating HTTP success as action success.\n\nAn acknowledgement can also reject or queue an action and carry reason and\nretryafterms without a ProtocolError. Treat those as acknowledgement\nstate, not as a substitute error object.\n\nCompact HTTP error\n\nSome pre-envelope or ergonomic routes return a compact object under error.\nExamples include JSON decoding before an envelope exists and capability-catalog\ndiscovery. A compact error can omit category, retry fields, or source. Use the\nroute's documented status and code; do not synthesize missing retry authority.\n\nModel Context Protocol mapping\n\nThe Model Context Protocol (MCP) profile maps AIP categories to JSON-RPC codes:\n\n| AIP category | JSON-RPC code |\n\n| auth | -32001 |\n| policy | -32003 |\n| temporary, transport | -32010 |\n| connector | -32020 |\n| economic | -32030 |\n| permanent | -32602 |\n\nWhen an AIP error has details, the current mapper uses those details directly\nas JSON-RPC data. When details are absent, data contains AIP extension\nmetadata with code, category, retry fields, and source. A generic MCP client\nmust therefore not assume that every projected failure exposes the AIP code.\n\nRetry decision order\n\nApply these checks in order. A later yes cannot override an earlier stop.\n\n| Check | Continue only when | Otherwise |\n\n| Outcome certainty | No side effect occurred, or the same effect can be reconciled safely | Read durable action or transaction state and reconcile |\n| Capability contract | supportsretry is true | Stop or follow the capability's recovery procedure |\n| Retry safety | Safety is safe, or safewithidempotencykey with a key present | Do not repeat the action |\n| Result state | The action result is failed | Follow the lifecycle for queued, pending, cancelled, or terminal success state |\n| Explicit error hint | retryable is not false | Stop; correct the cause instead |\n| Category fallback | retryable is true, or absent and the policy accepts the category | Stop unless a higher-level contract explicitly provides recovery |\n| Attempt and elapsed budget | Another bounded attempt fits both limits | Dead-letter, reconcile, or escalate |\n| Delay | Backoff and any retry hint fit the remaining budget | Stop or wait for a later operator decision |\n\nAt this revision, queued-runtime retry policy behaves as follows:\n• safe and safewithidempotencykey capabilities receive a maximum of\n  three attempts by default; unsafe and unknown receive one;\n• safewithidempotencykey cannot retry without an idempotency key;\n• retryable: false always stops the runtime retry;\n• retryable: true permits the error-hint gate, subject to every other gate;\n• absent retryable falls back to configured categories, whose default set is\n  temporary, transport, and connector;\n• retryafterms is clamped to at least 1 ms and at most the policy's maximum\n  backoff; absent delay uses bounded exponential backoff;\n• the retry is rejected if the next delay exceeds maxelapsedms.\n\nThese are current runtime defaults, not a protocol mandate for every AIP\nimplementation. A client should read durable status before resubmitting after\nan interrupted transport exchange.\n\nUnknown outcomes\n\nA transport failure after dispatch does not prove that a provider mutation did\nnot happen. A typed ConnectorFailure carries the evidence needed to choose a\nsafe branch:\n\n| Connector field | Recovery use |\n\n| providerrequestid | Correlate provider logs and support evidence |\n| provideroperation | Identify provider, operation ID, and optional request ID |\n| remotestatus | Record the downstream protocol status |\n| uncertainoutcome | Prevent blind replay when an external effect may exist |\n| operation | Identify discovery, admission, invocation, cancellation, streaming, health, transaction, reconciliation, compensation, emission, or ingestion |\n| redacteddetails | Retain bounded diagnostic evidence without raw provider data |\n| source | Identify the connector component that produced the failure |\n\nThe conversion to ProtocolError places these values in details and preserves\nthe connector's code, category, retry flag, and delay. Conversion in the other\ndirection treats absent retryable as false.\n\nFor transaction modes commit and execute, the runtime moves the transaction\ntoward outcomeunknown when the result has code sla.timeoutexceeded or\ndetails.uncertainoutcome is true. Use the captured provider operation ID and\nthe reconciliation action. Do not create a second mutation merely because a\ntransport or timeout category looks temporary.\n\nCommon native code families\n\nThe table lists product-neutral families implemented at the pinned revision.\nIt is a lookup aid, not an exhaustive registry of provider-specific codes.\n\n| Code or prefix | Typical meaning | Decision |\n\n| action.invalidinput | Required action data or a semantic invariant is invalid | Correct the action; unchanged retry is false |\n| capability.unsupported | The endpoint or manifest does not own the requested capability or message | Rediscover capabilities or choose another endpoint |\n| resource.notfound, receipt.notfound | Selected session, capability, resource, or receipt is absent | Check the identifier and tenant boundary |\n| handshake.nocompatibleprofile | No requested profile is supported | Negotiate a profile present in the manifest |\n| auth.nativehttpunauthorized | Native bearer authentication is missing, invalid, or not configured for the presented token | Correct authentication; do not retry with broader scopes |\n| auth., credential., audit.notauthorized | Actor, claim, tenant, session, credential, ownership, or scope does not match trusted context | Re-establish the intended identity and authority |\n| auth.signature.invalid, replay.messageid | Signature verification or replay fencing failed | Stop; correct signing, clock, message identity, or replay state |\n| query.invalid, query.invalidcursor | Query syntax or cursor format is invalid | Correct the query or restart pagination as documented |\n| stream.cursorexpired | Cursor is outside the retained replay window | Read current durable state, then restart from an available cursor |\n| idempotency.inprogress | Another action owns the scoped key until its reservation expires | Read the owning action; wait for the bounded retry delay |\n| policy.humanapprovalrequired | Execution is pending an approval lifecycle decision | Submit or await approval; do not retry the action |\n| sla.timeoutexceeded | The handler exceeded its effective action timeout | Inspect cancellation and outcome certainty before any retry |\n| sla.queuedelayexceeded | A queued action exceeded the capability's maximum queue delay | Stop or resubmit as a new authorized operation if appropriate |\n| storage.unavailable | Durable runtime storage failed | Retry only within policy; verify durable state before replay |\n| runtime.handlerfailed | A handler was missing or returned an implementation failure | Diagnose ownership and implementation before relying on retry |\n| manifest.admissionfailed, implementation. | Manifest or handler ownership admission failed | Fix deployment admission; client retry cannot repair it |\n| transaction. | Plan, commit, compensation, rollback, or reconciliation policy failed | Follow transaction state and its exact recovery branch |\n| delegation. | Target, route, depth, identity, or policy rejected delegation | Correct the delegation contract or authority |\n\nConnector-fleet runtime errors\n\nCatalog and central admission\n\nThe tenant capability-catalog route uses compact HTTP errors:\n\n| Code | HTTP status | Decision |\n\n| connectorcatalog.disabled | 404 | Configure the catalog; client retry cannot enable it |\n| connectorcatalog.tenantrequired | 403 | Bind the authenticated actor to a verified tenant |\n| connectorcatalog.invalidquery | 400 | Correct capability, profile, cursor, text, or limit input |\n| connectorcatalog.stalecursor | 409 | Discard the cursor and restart at the first page |\n| connectorcatalog.unavailable | 503 | Retry the read with bounded backoff |\n\nCentral remote routing and admission return structured protocol errors where\nthe condition has a stable client decision:\n\n| Code | Category and retry | Decision |\n\n| connector.requestrejected | permanent, false | Correct invalid limits or oversized work |\n| connector.scheduleroverloaded | temporary, true, 100 ms | Retry only within tenant fairness and action retry policy |\n| connector.admissioncapacity | temporary, true, bounded registry delay | Wait for the exhausted admission scope; do not bypass the quota |\n\nBinding absence, replica unavailability, stale registry state, fence loss, and\nstorage failures can surface through a broader runtime error when no dedicated\nprotocol mapping exists. Operators should inspect registry and fleet state\nrather than infer a specific code from generic handler text.\n\nConnector-host execution\n\nAuthenticated host requests receive a signed error envelope for these\nconditions:\n\n| Code | HTTP | Category and retry | Decision |\n\n| connectorhost.notready | 503 | temporary, true, heartbeat interval | Wait for a valid lease and ready non-draining host |\n| connectorhost.capacity | 429 | temporary, true, 100 ms | Respect local concurrency; do not scale by bypassing admission |\n| connectorhost.approvalauthorizationunavailable | 503 | temporary, true, 1,000 ms | Recover the approval journal and retry within policy |\n| connectorhost.approvalauthorizationconflict | 403 | auth, false | Reconcile the signed approval with durable host state |\n| connectorhost.credentialrevisionunavailable | 503 | temporary, true, 1,000 ms | Restore credential-revision resolution without changing the pin |\n| connectorhost.credentialrevisiondenied | 403 | auth, false | Correct tenant, instance, capability, or revision authorization |\n| connectorhost.routemismatch | 403 | auth, false | Discard the request and re-resolve the exact admitted route |\n| connectorhost.authentication | 401 | auth, false | Correct gateway identity, DID, signature, or trust domain |\n| connectorhost.replay | 409 | policy, false | Do not reuse the message ID; inspect prior execution state |\n| connectorhost.execution | 502 | connector, false | Diagnose the host runtime or unsupported message before retry |\n\nSchema/decode failures and response-signing failures occur before a trustworthy\nsigned response can be produced. Those paths use compact unsigned JSON with\n400 or 500. Treat an unsigned failure as transport evidence only; never accept\nits body as authenticated host state.\n\nEvent and stream-callback ingress\n\n| Code | Category and retry | Decision |\n\n| connectorevent.capacity | temporary, true, 100 ms | Retry the same idempotent event envelope within ingress bounds |\n| connectorevent.invalid | permanent, false | Correct envelope type, size, route, event, or chunk shape |\n| connectorevent.notauthorized | auth, false | Correct recipient, signer, route assignment, tenant, or binding |\n| connectorevent.idempotencyconflict | permanent, false | Stop: the event ID already owns different retained content |\n| connectorevent.unavailable | temporary, true, 1,000 ms | Recover registry or durable event state before bounded retry |\n| connectorevent.notconfigured | permanent, false | Configure central ingress before sending callbacks |\n\nRegistry and admission operator failures\n\nRegistry and admission CLI commands fail through standard error and non-zero\nexit status. Their Rust error families are not ProtocolError codes and do not\ncarry a wire-level retry flag.\n\n| Failure family | Meaning | Operator action |\n\n| Admission Invalid | Package, policy, identity, limit, or invariant is invalid | Correct the document; do not retry unchanged |\n| Admission Signature | Package or evidence signature cannot be verified | Stop and correct the signer, DID, signature, or canonical object |\n| Admission Evidence | Required evidence is missing, stale, mismatched, revoked, or rejected | Replace or regenerate the exact evidence set |\n| Admission Registry | Applying the verified package failed in catalog storage | Read the durable admission operation before safely resuming |\n| Admission Journal | The durable operator journal failed | Restore journal authority and inspect partial state |\n| Admission Conflict | Package identity, revision, digest, or terminal revoke conflicts | Reconcile the exact recorded operation; never overwrite it |\n| Registry BindingUnavailable | No enabled tenant binding owns the capability | Correct or enable the admitted binding |\n| Registry ReplicaUnavailable | No ready replica has capacity | Restore host lease/readiness or scale through admitted orchestration |\n| Registry CapacityExceeded | A hard admission counter reached its limit | Respect its bounded retry delay or change approved capacity |\n| Registry StaleCursor | Catalog revision changed during pagination | Restart the catalog query from the first page |\n| Registry FenceLost | Route assignment fencing failed | Discard the route and resolve a new fenced assignment |\n| Registry Storage | Durable registry access failed | Recover storage, then inspect the exact operation before retry |\n\nUse connector registry plan to verify without writing. apply journals and\nresumes an exact package revision and digest; status is the recovery source.\nDo not repeatedly invoke apply based only on an error string.\n\nCallback and delivery failures\n\nAction execution, callback delivery, and event ingestion are separate durable\nboundaries. A completed action can coexist with a failed callback. Recover the\ncallback from its durable outbox or event state; do not rerun the provider\naction to compensate for delivery failure.\n\nLikewise, a successful transport response can contain a failed action result,\nand a failed transport exchange can leave an action running. Read action,\ntransaction, event, and receipt state before choosing another mutation.\n\nSecurity and observability\n• Log code, category, action ID, transaction ID, correlation ID, retry decision,\n  attempt, and redacted source metadata.\n• Do not log credentials, raw provider bodies, bearer tokens, signing seeds, or\n  unreviewed details.\n• Keep one metric label set per bounded code family; do not label by free-form\n  message, tenant, provider request ID, or resource ID.\n• Treat signature, tenant, route, credential-revision, approval-conflict,\n  replay, and fence failures as security events, not ordinary availability.\n• Preserve durable receipts and provider operation references for an unknown\n  outcome or contested retry.\n\nRelated reference\n• Native HTTP API (http-api.md)\n• Connector fleet HTTP API (connector-fleet-api.md)\n• Transport bindings (transport-bindings.md)\n• getaip CLI (cli.md)\n• Actions and sessions (../concepts/actions-and-sessions.md)\n"
  },
  "integrity": {
    "algorithm": "sha256",
    "sourceDigest": "1d1294fe3618ef898f8e19aeb313edf7f7bd320a57d877502beca7789e60a3a5"
  }
}
