# Errors

Every failure is an RFC 9457 problem (`application/problem+json`). `type` names the kind,
`reason` is the machine-readable why, `retryable` says whether repeating the same request
can succeed, and `requestId` is what to quote. A resource that belongs to someone else
answers exactly like a missing one.

```json
{ "type": "urn:fin:error:conflict", "title": "Conflict", "status": 409,
  "reason": "run_active", "requestId": "0192…", "retryable": false }
```

- `run_active` (409) — a run already holds this conversation
- `budget_exhausted` (409) — the user's spend headroom is gone, or an operator froze it
- `approval_not_pending` (409) — the approval was already decided or has expired, or its id does not exist or belongs to a different conversation
- `execution_capacity` (409) — no execution capacity is free right now; `retryable` says whether to try again
- `execution_unavailable` (409) — the execution engine could not take the work
- `stop_pending` (409) — a stop is already in progress and its cleanup is not yet confirmed
- `automation_changed` (409) — the `revision` sent is stale; reload the automation
- `automation_held` (409) — an operator holds the automation; it fires again when released
- `automation_invalid` (409) — the automation's definition cannot run as written
- `automation_completed` (409) — the automation has finished for good and cannot fire again
- `profile_unknown_tool` (409) — the run profile names a tool this deployment does not have
- `deployment_paused` (409) — an operator paused a deployment control; nothing was admitted or fired
- `run_not_active` (409) — the run named in the path is not the conversation's live run
- `withdrawal_changed` (409) — the withdrawal cannot be prepared or confirmed as asked: the balance no longer covers it, its terms changed or expired, or it is already in progress
- `credential_expired` (401) — the user token has expired; obtain a fresh one
- `account_disabled` (403) — an operator disabled the account
- `account_not_provisioned` (412) — the identity is verified but has no account yet; call `users.ensure` first
- `provider_unavailable` (503) — an external provider the call depends on did not answer
- `invalid_input` (400) — the body or query failed validation; `issues` names each field
- `internal` (500) — a fault on our side; quote `requestId` when reporting it
- `partner_key_required` (401) — no `X-Api-Key` header was sent
- `partner_key_invalid` (401) — the `X-Api-Key` is unknown or revoked
- `subject_mismatch` (403) — the `{userId}` in the path is not the token's user
- `origin_rejected` (403) — a browser `Origin` other than the configured web origin
- `rate_limited` (429) — the per-key or per-user limit is spent; honour `Retry-After`
- `stream_capacity` (429) — no stream socket is free on this replica or for this user; honour `Retry-After`
- `invalid_cursor` (400) — the `cursor` is not one this list minted
