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.

CodeConditionMeaningTypical handling
acceptedall nine conditions passed; verified is presentproceed
request_malformedpreconditionthe challenge body violates the §10.5 shape (e.g. empty claim policy)fix challenge construction
verifier_not_active1your verifier registration is not ACTIVE on proven statecheck your registry state
origin_not_registered1the origin does not resolve to your verifier (no trust-by-name)register/renew the exact origin
revalidation_expired1domain-control proof for the origin lapsedrenew (MsgRenewVerifierOrigin)
request_key_not_active2the challenge's signing key is unregistered or rotated outrotate/register keys properly
nonce_replayed3this challenge's nonce was already consumedissue a fresh challenge; investigate replays
deadline_exceeded4the response arrived at or after the 10-second deadlineissue a fresh challenge
proof_invalid5the proof failed verification or is bound to a different challenge contextreject; possible tampering
predicate_missing6a requested predicate is not among the proven onesreject; holder cannot satisfy policy
issuer_not_accepted7the credential's issuer is outside your accepted-issuer policypolicy decision — yours
issuer_not_active7the issuer is not operational (or below your state minimum)reject; retry later is legitimate
status_root_stale7proof built against a superseded root, or the root expired (fail closed)holder retries with a fresh proof
height_stale8the challenge's chain height fell outside [latest − max_height_lag, latest]issue a fresh challenge
state_unproven1/8a chain read could not be cryptographically proven — including claimed absenceinfrastructure alert; never bypass
nonce_race_lost9a 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:

CodeWhy it cannot occur
origin_invalida non-exact origin already fails the shape precondition and rejects as request_malformed
domain_validation_failedabstract base reason; concrete subclasses are always raised instead