> ## Documentation Index
> Fetch the complete documentation index at: https://docs.anchorage.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors and retries

> What each failure means, and whether to retry with the same idempotency key.

What each failure means, and whether to retry with the same idempotency key.

| Failure | What to do | Idempotency key |
| - | - | - |
| Over the budget cap (`budget_limit_reached`; inference returns `payment_declined`) | Ask an org admin to raise the cap, then pay again | New |
| Merchant not active or not on the allowlist | Pick another merchant | n/a |
| Inference provider not on the allowlist (`payment_declined`) | Add the provider to the budget's allowlist | New |
| Merchant returned a 5xx | Retry | Same |
| Daily cap reached | Wait for the next UTC day | n/a |
| Agent is paused | Its owner resumes it from the agent page | Same |
| HTTP 429 | Wait for `Retry-After`, then retry | Same |

An over-budget payment is declined, with no approval path, so don't poll for one. See [Over budget](https://docs.anchorage.com/agentic-banking/concepts/payments.md#over-budget). For the daily cap, see [Limits](https://docs.anchorage.com/agentic-banking/reference/limits.md). To resume a paused agent, see [Pause or revoke an agent](https://docs.anchorage.com/agentic-banking/guides/pause-or-revoke-an-agent.md).

## Payment failures

| Verdict | What it means | What to do |
| - | - | - |
| Compliance mismatch | Merchant not on allowlist or inactive | Pick a different merchant |
| Spending mismatch | Over the budget cap | Declined with no approval path: a fixed-price payment with `budget_limit_reached`, and a metered payment whose per-request maximum exceeds the remaining budget with its own decline reason. Once an org admin raises the cap, send a new payment with a new idempotency key (see [Over budget](https://docs.anchorage.com/agentic-banking/concepts/payments.md#over-budget)) |
| Daily cap reached | Hard reject, no approval path | Wait for the next UTC day. See [Limits](https://docs.anchorage.com/agentic-banking/reference/limits.md) |
| Agent deactivated | Hard reject, no approval path | See [Pause or revoke an agent](https://docs.anchorage.com/agentic-banking/guides/pause-or-revoke-an-agent.md) |
| Account locked or frozen | Hard reject, no approval path | Contact Anchorage support — resolution requires staff action |
| Insufficient account balance | Hard reject, no approval path | Fund the account, then retry |
| Resource mismatch | The merchant's quote names a resource at a different address (host or port) than the URL actually reached | Hard reject, no approval path. The merchant endpoint is misconfigured; pick a different merchant |
| Schema mismatch | Request body doesn't match the merchant's published schema | Fix the request body and retry with a **new** idempotency key |
| Key already used with another protocol | A repeat call met a different payment protocol than the original payment used; nothing new was paid | Check the named payment's status. Before you use a **new** idempotency key, confirm with Anchorage support that it did not settle: a pending, declined, or expired payment can still turn out to have paid |
| Upstream 5xx | Merchant indeterminate | Retry with the **same** idempotency key — repeat calls collapse to one settlement |
| Interrupted while signing | The payment stopped before an authorization was recorded; reserved funds stay held | Retry with the **same** idempotency key — contact Anchorage support if retries keep failing |

## Inference failures

Every error these inference endpoints return once they accept a request is
an OpenAI-compatible JSON body, `{"error": {"message", "type", "code"}}`, so an
OpenAI SDK or a client built on one shows `error.message` to the user as-is:
`POST /v1/chat/completions`, `GET /v1/models`, the image, video, and audio
generation routes, and their status polls. `POST /v1/messages` returns the
same errors in Anthropic's shape, covered in
[Anthropic Messages API](https://docs.anchorage.com/agentic-banking/concepts/inference.md#anthropic-messages-api). `POST /v1/decide` keeps its
own error shape, covered in [Typed judgments](https://docs.anchorage.com/agentic-banking/concepts/inference.md#typed-judgments).
Three kinds of request are rejected before they reach an inference endpoint,
with a non-JSON body instead: an HTTP method the route doesn't serve gets `405
Method Not Allowed`, except on `/v1/messages`, which answers in its own JSON
error shape; a request whose declared `Content-Length` is over 2 MiB gets `413
Request Entity Too Large`, except a `POST` to an inference endpoint that takes
`POST`, which refuses an oversized body in its own JSON error shape; and an
unsafe browser request from another site, such as a cross-site `POST`, gets
`403 Forbidden`. These non-JSON responses carry no `error.code` and no
`x-should-retry`, so handle them by HTTP status. For every other error, the
message says what happened, and the table below says what to do; branch on
`error.code`. Each of those responses also carries `x-should-retry: true` or
`false`, which the OpenAI SDKs follow when deciding whether to retry on their
own. When a payment was submitted, the message names the transaction and the
response carries it in `X-Transaction-ID`, and the message says how to resend
the request without paying twice: the identical request, with the same
`Idempotency-Key` if you sent one, and with none added if you didn't. The message never
quotes the model provider's own error text.

| Status | `error.code` | What it means | What to do |
| - | - | - | - |
| 401 | `invalid_api_key` | No usable agent API key. | Mint or check the key on the agent's page. |
| 400 | `invalid_request` | The request body couldn't be read, is over 1.5 MiB, or its `Idempotency-Key` is over 255 characters. The message says which. Nothing charged. | Fix the request. |
| 400 | `streaming_not_enabled` | The request set `"stream": true` on an endpoint that doesn't stream. Nothing charged. | Send the request with `"stream": false`, or omit the field. |
| 400 | `provider_rejected_request` | The model provider rejected the request, for example an unknown model name. When a payment was submitted, the message and `X-Transaction-ID` name it. | Fix the request. `GET /v1/models` lists the model names. If a payment was submitted, check that transaction before retrying. |
| 403 | `budget_not_configured` | No spend limit configured. | Configure a budget, then retry. A retry with the `Idempotency-Key` of a request you already paid for goes through to that payment. |
| 402 | `budget_approval_required` | A request from before over-budget requests started declining that was left waiting on an admin. It no longer completes, even after approval. A request over the budget cap now returns `payment_declined`. | Send a new request with a new `Idempotency-Key` once the budget allows it. |
| 403 | `daily_limit_reached` | The agent reached its [daily spending cap](https://docs.anchorage.com/agentic-banking/reference/limits.md). Nothing charged. | Retry after the cap resets. |
| 403 | `budget_inactive` | The agent's budget isn't active. Nothing is charged unless the message names a transaction. | Activate the budget, then retry. When the message says Anchorage recorded the decline, it names the declined transaction in the message and the `X-Transaction-ID` header, and the identical request is declined again: check the transaction before you send it again. |
| 403 | `insufficient_funds` | The account doesn't have enough funds for this request. Nothing is charged unless the message names a transaction. | Add funds, then retry. When the message says Anchorage recorded the decline, it names the declined transaction in the message and the `X-Transaction-ID` header, and the identical request is declined again: check the transaction before you send it again. |
| 403 | `payment_declined` | The payment was declined: a compliance, spending (the budget cap, with a message that the payment would take the budget past its cap), or account-status check, a per-payment or program limit, or a payment the model provider asked for that Anchorage can't make for this request. The message gives the reason when it's known. When it gives a reason and names no transaction, nothing was charged. When it says Anchorage can't confirm whether the payment went through, the payment may have been made. When it says the request matches an earlier payment that used a different payment protocol, it names that payment's transaction ID in the message and the `X-Transaction-ID` header, and nothing new was paid. | Act on the reason, then retry. For a budget limit, an org admin raises the cap, and you then retry with a new `Idempotency-Key`. When the message says Anchorage recorded the decline, it names the declined transaction in the message and the `X-Transaction-ID` header, and the identical request is declined again: check the transaction before you send it again. When the message can't confirm the payment, send the identical request again with the same `Idempotency-Key` if you sent one, and with none added if you didn't: it returns any payment already made instead of paying again. See [Payment failures](#payment-failures). |
| 503 | `platform_unavailable` | A temporary problem on Anchorage's side stopped the payment. Your budget didn't cause it. When a payment was submitted, the message and `X-Transaction-ID` name it. Otherwise the message says Anchorage can't confirm whether the payment went through. | When the response carries `x-should-retry: true`, retry in a few minutes with the identical request and the same `Idempotency-Key` if you sent one, and with none added if you didn't: it returns any payment already made instead of paying again. When the message names a transaction, the response carries `false`: check that transaction instead, since resending returns the same recorded answer. |
| 409 | `payment_request_expired` | The model provider's payment request expired before Anchorage could pay it. Nothing charged. | Retry the request. |
| 502 | `provider_unavailable` | The model provider is unavailable or unreachable. Nothing charged. | Retry in a few minutes. |
| 429 | `rate_limit_exceeded` | The model provider is rate limiting requests, or Anchorage is limiting how often new payment destinations can be set up. When a payment was submitted, the message and `X-Transaction-ID` name it. | When the response carries `x-should-retry: true`, wait for the `Retry-After` delay if it has one, otherwise back off, then retry. When a payment was submitted, the response carries `false`: check that transaction instead, since resending can return the same recorded answer. |
| 502 | `paid_no_response` | A payment was submitted but no usable completion came back: the provider refused the payment, returned a server error, or returned an answer too large to record. The message and `X-Transaction-ID` name the transaction. | Check that transaction before you send the request again, and resend the way the message says to avoid paying twice. If it stays pending, contact Anchorage support. |
| 403 | `origin_not_permitted` | Refused before this endpoint's own request handling ran (for example, a compliance check on the connection). Nothing charged. | See [Payment failures](#payment-failures). |
| 500 | `internal_error` | Something went wrong on Anchorage's side. | Retry in a few minutes when the response carries `x-should-retry: true`; when it carries `false`, the same request fails the same way, so contact Anchorage support. |
| 404 | `generation_job_not_found` | A generation status poll named no job of this kind that belongs to this agent. | Check the id and the route. |


## Related topics

- [Call a paid API](https://docs.anchorage.com/agentic-banking/guides/call-a-paid-api.md)
- [Paid inference](https://docs.anchorage.com/agentic-banking/concepts/inference.md)
- [Crypto payments](https://docs.anchorage.com/agentic-banking/concepts/payments.md)
- [Changelog](https://docs.anchorage.com/agentic-banking/changelog.md)
- [Call a text model](https://docs.anchorage.com/agentic-banking/guides/call-a-text-model.md)
