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

# Errors

> Handle Checkfu's stable typed error envelope, distinguish settled decisions from transient failures, and avoid unsafe provider retries.

Every versioned JSON error uses the same envelope:

```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
{
  "error": {
    "type": "runtime.invalid_transition",
    "message": "cannot drive a terminal session",
    "more": "https://docs.checkfu.com/reference/errors#runtime-invalid-transition"
  }
}
```

Switch on `error.type`, not the human-readable message. The message can be
reworded. The type and its structured fields are the wire contract.

<Note>
  A typed route and typed error do not prove that the capability is available.
  Support also depends on audience, stability, topology, prerequisites, and
  live evidence. Check [capability status](/getting-started/status) when an
  error indicates an unavailable runtime or provider lane.
</Note>

## Namespaces

| Namespace | Meaning | Typical resolver |
| - | - | - |
| `validation` | Request shape, identity, conflict, or bounded-read failure | Caller |
| `auth` | Credential authentication or unavailable authorization evaluation | Caller, Organization administrator, or operator |
| `policy` | Governance or retention made a settled deny decision | Workspace administrator |
| `budget` | Budget, quota, ceiling, or rate limit refused capacity | Workspace administrator |
| `billing` | Commercial entitlement or payment blocks Checkfu-funded work | Organization administrator |
| `model` | No admitted model source or credential can serve the call | Workspace administrator or operator |
| `memory` | Memory operation failed or is unavailable | Varies |
| `runtime` | Session, harness, runner, observation, or transition failure | Varies |

Internal failures return an incident reference rather than stack or
credential-bearing context.

## Error registry

This table gives the complete error vocabulary's default HTTP status and
retryability. Each public operation declares its own error responses in the
[API reference](/reference/overview). Use that operation's declared responses when
handling an HTTP request; a registry entry alone does not declare a response
for an operation.

The vocabulary also retains lifecycle and diagnostic codes that no current
public operation declares as a typed HTTP response. For example,
`runtime.lease_lost`, `runtime.harness_failed`, and `retention.zdr_unsupported`
are registry entries, not additional quickstart request errors. A code in a
Session outcome or diagnostic record does not give that record an HTTP status
or authorize repeating its provider effect.

| Type | HTTP | Retry the same idempotent request |
| - | -: | - |
| <a id="validation-malformed">validation.malformed</a> | 400 | No |
| <a id="validation-prompt-integrity-review-required">validation.prompt\_integrity\_review\_required</a> | 400 | No |
| <a id="validation-not-found">validation.not\_found</a> | 404 | No |
| <a id="validation-conflict">validation.conflict</a> | 409 | No |
| <a id="validation-idempotency-conflict">validation.idempotency\_conflict</a> | 409 | No |
| <a id="validation-idempotency-in-progress">validation.idempotency\_in\_progress</a> | 409 | Yes |
| <a id="validation-payload-too-large">validation.payload\_too\_large</a> | 413 | No |
| <a id="validation-range-too-large">validation.range\_too\_large</a> | 422 | No |
| <a id="auth-invalid-key">auth.invalid\_key</a> | 401 | No |
| <a id="auth-disabled-tenancy">auth.disabled\_tenancy</a> | 403 | No |
| <a id="auth-authorization-unavailable">auth.authorization\_unavailable</a> | 503 | Yes |
| <a id="auth-request-admission-unavailable">auth.request\_admission\_unavailable</a> | 503 | Yes |
| <a id="policy-denied">policy.denied</a> | 403 | No |
| <a id="budget-exceeded">budget.exceeded</a> | 429 | No |
| <a id="model-no-eligible-model">model.no\_eligible\_model</a> | 422 | No |
| <a id="model-credential-rejected">model.credential\_rejected</a> | 422 | No |
| <a id="model-platform-supply-unavailable">model.platform\_supply\_unavailable</a> | 503 | Yes |
| <a id="model-platform-capacity-reached">model.platform\_capacity\_reached</a> | 503 | Yes |
| <a id="billing-entitlement-unavailable">billing.entitlement\_unavailable</a> | 503 | Yes |
| <a id="billing-usage-limit-reached">billing.usage\_limit\_reached</a> | 402 | No |
| <a id="billing-payment-required">billing.payment\_required</a> | 402 | No |
| <a id="billing-seat-activation-unavailable">billing.seat\_activation\_unavailable</a> | 503 | Yes |
| <a id="memory-not-found">memory.not\_found</a> | 404 | No |
| <a id="memory-conflict">memory.conflict</a> | 409 | No |
| <a id="memory-read-only">memory.read\_only</a> | 403 | No |
| <a id="memory-invalid-path">memory.invalid\_path</a> | 400 | No |
| <a id="memory-backend-unavailable">memory.backend\_unavailable</a> | 503 | Yes |
| <a id="memory-curation-failed">memory.curation\_failed</a> | 422 | No |
| <a id="runtime-invalid-transition">runtime.invalid\_transition</a> | 409 | No |
| <a id="runtime-primary-thread">runtime.primary\_thread</a> | 409 | No |
| <a id="retention-zdr-unsupported">retention.zdr\_unsupported</a> | 403 | No |
| <a id="runtime-checkpoint-expired">runtime.checkpoint\_expired</a> | 409 | No |
| <a id="runtime-session-history-unavailable">runtime.session\_history\_unavailable</a> | 409 | No |
| <a id="runtime-harness-unavailable">runtime.harness\_unavailable</a> | 503 | Yes |
| <a id="runtime-harness-failed">runtime.harness\_failed</a> | 502 | Yes |
| <a id="runtime-runner-unavailable">runtime.runner\_unavailable</a> | 503 | Yes |
| <a id="runtime-provider-host-unavailable">runtime.provider\_host\_unavailable</a> | 503 | Yes |
| <a id="runtime-lease-lost">runtime.lease\_lost</a> | 409 | No |
| <a id="runtime-start-timeout">runtime.start\_timeout</a> | 503 | Yes |
| <a id="runtime-allocation-failed">runtime.allocation\_failed</a> | 502 | No |
| <a id="runtime-allocation-not-ready">runtime.allocation\_not\_ready</a> | 409 | Yes |
| <a id="runtime-provisioning-suspended">runtime.provisioning\_suspended</a> | 503 | Yes |
| <a id="runtime-computer-unavailable">runtime.computer\_unavailable</a> | 503 | No |
| <a id="runtime-turn-deadline-exceeded">runtime.turn\_deadline\_exceeded</a> | 504 | No |
| <a id="runtime-observation-gap">runtime.observation\_gap</a> | 409 | Yes |
| <a id="runtime-observation-conflict">runtime.observation\_conflict</a> | 409 | No |
| <a id="runtime-attestation-invalid">runtime.attestation\_invalid</a> | 400 | No |
| <a id="runtime-harness-incompatible">runtime.harness\_incompatible</a> | 422 | No |
| <a id="runtime-target-mismatch">runtime.target\_mismatch</a> | 409 | No |
| <a id="runtime-transcript-index-unavailable">runtime.transcript\_index\_unavailable</a> | 503 | No |
| <a id="runtime-managed-tool-failed">runtime.managed\_tool\_failed</a> | 502 | No |
| <a id="runtime-managed-tool-canceled">runtime.managed\_tool\_canceled</a> | 409 | No |
| <a id="runtime-internal">runtime.internal</a> | 500 | Yes |

"Yes" means the same idempotent Checkfu request is transport-safe to retry
according to the typed error contract. It does not mean an external provider
effect is known not to have happened.

## Authorization availability

`auth.authorization_unavailable` means Checkfu could not evaluate authorization.
It returns HTTP 503 with the fixed message "Authorization could not be evaluated.
Retry the same request." The public error does not expose the underlying store,
credential, policy, or diagnostic cause. Retry the same idempotent request after
authorization becomes available; do not replace its idempotency key.

This differs from an invalid credential (`auth.invalid_key`) and a settled deny
(`policy.denied`). An unavailable Memory content backend retains its distinct
`memory.backend_unavailable` error. A retryable authorization error does not, by
itself, prove that an external provider effect did not occur.

## Principal request admission

`auth.request_admission_unavailable` (HTTP 503, retryable) means the Principal MCP
request-rate admission could not be evaluated. Retry the same request. The response
contains no binding, bucket, identity, or underlying failure details.

Authenticated Principal MCP requests share an edge-local limit of 120 requests per
60 seconds for each Workspace and Principal. Credential rotation retains the same
bucket. Exhaustion returns `budget.exceeded` (HTTP 429) with `Retry-After: 60`.
Authority and revocation checks remain independent; admission grants no permission
or spending authority. Trusted-source pre-authentication protection is not installed.

## Settled decisions

These errors require a change in authority or configuration, not blind retry:

| Type | What it means |
| - | - |
| `auth.invalid_key` | The key is missing, unknown, or revoked. |
| `policy.denied` | Permission, policy, retention, or another governed check made a settled deny decision. |
| `budget.exceeded` | A Budget, Workspace quota, ToolInvocation ceiling, or API-key rate limit refused capacity. It does not identify a Budget resource by itself. |
| `billing.payment_required` | Payment state blocks new Checkfu-funded work. |
| `billing.usage_limit_reached` | Commercial entitlement is exhausted. |
| `model.no_eligible_model` | Every configured model candidate violated an admitted constraint or prerequisite. |
| `model.credential_rejected` | An already-admitted provider effect's selected Workspace credential was rejected or revoked. New Session admission with a revoked or rejected pinned credential is refused with HTTP 409 `validation.conflict`. Checkfu does not silently substitute platform supply. |
| `runtime.session_history_unavailable` | Required retained history is unavailable, including content omitted under ZDR or removed by retention or erasure. Retry cannot recreate it. |
| `validation.idempotency_conflict` | The idempotency key was reused with a different request body. |

`validation.range_too_large` is not a truncated success. The typed read refused
because the bounded range cannot be decoded under its current limit.

### Wire version skew

Every general REST request carries a dated `Checkfu-Version` header, and every response
to a supported version echoes it. When a client sends a version the server does
not serve, the server answers `validation.malformed` and names the versions it
accepts. The refusal may advertise the server's supported version in its response
header; that is not acceptance of the version the request sent. The TypeScript
SDK pins its version as `WIRE_VERSION` and
reports this case through `isWireVersionUnsupportedError(error)`, with a message
that names the version it sent. Retrying cannot fix it: update the SDK or CLI to a
release that matches the server. `checkfu doctor` reports the same mismatch for the CLI.

## Settled Managed Tool outcomes

`runtime.managed_tool_failed` and `runtime.managed_tool_canceled` report the
original call's settled terminal outcome. The Session receives a masked error;
provider diagnostics remain private. These outcomes do not authorize a new
purchase or an automatic provider retry. Inspect the original Session event log
and Usage for execution and accounting facts.

## Transient failures

For a retryable type, use exponential backoff and jitter and preserve the same
idempotency key and request body when the route supports them.

`validation.idempotency_in_progress` means another request with the same key is
still running. Retry the identical request. Do not generate a new key merely to
bypass the in-progress result.

`runtime.observation_gap` means execution evidence arrived out of order. Repeat
the same observation write; do not synthesize the missing provider event.

`runtime.provider_host_unavailable` means the provider webhook runtime is
unavailable. This includes a deployment without a configured provider catalog
and an unreachable configured host. A catalog failure does not prove a provider
request was sent. A lifecycle request may already have changed the provider
before its response was lost. Reconcile the same original request, preserving
its idempotency key when one was used, rather than dispatching a replacement.

`runtime.provisioning_suspended` means the current runtime lane entered a
cooldown after repeated provisioning failures. It is an availability result,
not evidence that a different unqualified provider is safe to select.

## Indeterminate external effects

A timeout, gateway failure, lost lease, or provider error can occur after an
external system accepted a request. In that case:

1. read the Session event log and Audit disposition;
2. use the provider's admitted lookup or idempotency mechanism when available;
3. preserve the original operation identity; and
4. leave the effect indeterminate until reconciliation establishes the result.

Do not translate a retryable Checkfu transport error into an exactly-once
provider claim. Retrying with a new provider operation identity can duplicate
an effect.

## CLI exit codes

The CLI maps HTTP and domain failure classes to stable process exits:

| Exit | Class | Covers |
| - | - | - |
| `0` | success | No failure |
| `1` | usage | Request-shape errors, unmapped client errors, or a domain outcome delivered successfully |
| `2` | network | Transport failure reaching the API |
| `3` | auth | Authentication or authorization failure |
| `4` | not\_found | Typed not-found response |
| `5` | conflict | Typed conflict |
| `6` | invalid | Semantically unprocessable request |
| `7` | rate\_limited | `429 budget.exceeded` |
| `8` | server | Server or upstream failure |
| `9` | billing | Commercial payment or entitlement failure |

`130` and `143` represent `SIGINT` and `SIGTERM`. `checkfu session chat` also
uses `130` when the remote Session is canceled. Read the Session event log for
execution truth; HTTP failure classes and chat turn outcomes are separate exits.

### Chat outcome exits

After a dispatched turn reaches its Session boundary, `checkfu session chat`
returns the following process exit:

| Session boundary | Exit |
| - | - |
| `session.status_failed` | `1` |
| `session.status_canceled` | `130` |
| `session.status_idle` with `retries_exhausted` | `1` |
| Idle with `end_turn`, `requires_action`, `interrupted`, `max_tokens`, `max_turn_requests`, `refusal`, `error`, or `budget_reached` | `0` |

Exhausted retries fail the chat turn even though the Session remains addressable.
A custom tool request still waits for its result before chat finishes.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.