<!-- markdown mirror of https://mintid.net/en/sdk/reason-codes — generated at build time -->

> The closed decision vocabulary, byte-identical across the Python SDK, the HTTP contract and every client — producible codes, handling, and the reserved set.

index — 12 documents

1.  [overviewsdk/00](/en/sdk)
2.  [getting startedsdk/01](/en/sdk/getting-started)
3.  [python sdksdk/02](/en/sdk/python)
4.  [service modesdk/03](/en/sdk/service-mode)
5.  [typescript clientsdk/04](/en/sdk/typescript-client)
6.  [mcp serversdk/mcp](/en/sdk/mcp-server)
7.  [conformancesdk/05](/en/sdk/conformance)
8.  [reason codessdk/06](/en/sdk/reason-codes)
    *   [producible codes](#producible)
    *   [reserved codes](#reserved)
9.  [adr-0001 · kyc trust modeladr/0001](/en/sdk/adr-0001-kyc-trust-model)
10.  [adr-0002 · packagingadr/0002](/en/sdk/adr-0002-packaging)
11.  [adr-0003 · multi-languageadr/0003](/en/sdk/adr-0003-multilanguage)
12.  [bip-0001 · contract freezebip/0001](/en/sdk/bip-0001-verifier-service-contract)

SDK docs · sdk/06

# Reason codes

The closed decision vocabulary, byte-identical across the Python SDK, the HTTP contract and every client — producible codes, handling, and the reserved set.

## Producible codes

The closed decision vocabulary, byte-identical across the Python SDK, the HTTP contract and every client. Any change is a major version of the contract and flows to every language at once — your `switch` will not silently meet an unknown code within a contract major.

Code

Condition

Meaning

Typical handling

`accepted`

—

all nine conditions passed; verified is present

proceed

`request_malformed`

precondition

the challenge body violates the signed-challenge shape (e.g. empty claim policy)

fix challenge construction

`verifier_not_active`

1

your verifier registration is not ACTIVE on proven state

check your registry state

`origin_not_registered`

1

the origin does not resolve to your verifier (no trust-by-name)

register/renew the exact origin

`revalidation_expired`

1

domain-control proof for the origin lapsed

renew (MsgRenewVerifierOrigin)

`request_key_not_active`

2

the challenge's signing key is unregistered or rotated out

rotate/register keys properly

`nonce_replayed`

3

this challenge's nonce was already consumed

issue a fresh challenge; investigate replays

`deadline_exceeded`

4

the response arrived at or after the 10-second deadline

issue a fresh challenge

`proof_invalid`

5

the proof failed verification or is bound to a different challenge context

reject; possible tampering

`predicate_missing`

6

a requested predicate is not among the proven ones

reject; holder cannot satisfy policy

`issuer_not_accepted`

7

the credential's issuer is outside your accepted-issuer policy

policy decision — yours

`issuer_not_active`

7

the issuer is not operational (or below your state minimum)

reject; retry later is legitimate

`status_root_stale`

7

proof built against a superseded root, or the root expired (fail closed)

holder retries with a fresh proof

`height_stale`

8

the challenge's chain height fell outside \[latest − max\_height\_lag, latest\]

issue a fresh challenge

`state_unproven`

1/8

a chain read could not be cryptographically proven — including claimed absence

infrastructure alert; never bypass

`nonce_race_lost`

9

a concurrent presentation consumed the nonce first (atomic accept gate)

reject; exactly one winner exists

Notes:

*   **Issuer-state policy nuance (condition 7):** with the default `issuer_state_minimum: "ACTIVE"`, an issuer under enhanced monitoring rejects as `issuer_not_active`; opting into `"ENHANCED_MONITORING"` accepts it. This is the only policy knob in the vocabulary's behavior, and it is _your_ policy, expressed in the challenge.
*   **`state_unproven` is your pager, not your bug.** It means the SDK refused to decide on unproven state — a node lying, a proof failing, an anchor unreachable. The correct response is operational, never a retry-until-accept loop.

## Reserved codes

Present in the contract enum for defense in depth; structurally unreachable through the validation entrypoint — do not wait for them:

Code

Why it cannot occur

`origin_invalid`

a non-exact origin already fails the shape precondition and rejects as `request_malformed`

`domain_validation_failed`

abstract base reason; concrete subclasses are always raised instead

[previous← conformance](/en/sdk/conformance)[nextadr-0001 · kyc trust model →](/en/sdk/adr-0001-kyc-trust-model)

---
Source: https://mintid.net/en/sdk/reason-codes · Reason codes — MintID verifier SDK docs
