Errors#
The strings your app branches on when a deed fails to verify, plus the handful an operator's own boot-time self-check can raise. Source of truth: crates/grantor-verify/src/guard.rs's Rejected enum — the same codes in every language.
Verifying a presented deed#
These are what DeedGuard/DeedVerifier returns from a normal request — see Verify a deed. code() is the stable string an app branches on.
| HTTP | Code | When it happens |
|---|---|---|
401 | MissingDeed | The caller sent no X-Grantor-Deed header. |
401 | MissingChallenge | The caller sent no X-Grantor-Challenge header. |
401 | UnknownChallenge | The challenge is unissued, expired, or already spent — burned before verification, so this also fires for a flood of bogus deeds. |
401 | BadDeedEncoding | The deed header is not base64url JSON (a bare JSON object is tolerated). |
401 | UnsupportedMode | token.mode is not one this verifier accepts (only agent-zk/user-sig reach verify_deed; admin-sig has its own entry point). |
401 | WrongAudience | The deed was minted for a different aud/tenant than this DeedPolicy. |
401 | ChallengeMismatch | The deed is bound to a different challenge than the one presented. |
401 | Expired | Past its own exp, or exp exceeds the policy's max_ttl_secs. |
401 | Malformed | Wrong field shape for its claimed mode (e.g. agent-zk carrying pubkey/signature, or user-sig carrying root/proof). |
401 | BadProof | The ECDSA signature (user-sig) or Semaphore ZK proof (agent-zk) failed to verify. |
401 | StaleRoot | agent-zk only — the membership root has aged out of the registry's recent-root window; possible revocation. |
401 | TenantInactive | Billing — the tenant is neither Active nor Grace on-chain. |
503 | Chain | An on-chain read (eth_call) failed. |
Chain is 503 rather than 401 deliberately: an RPC outage is not the caller's fault, and answering 401 sends clients into a login loop that discards good credentials and cannot succeed. The verifier fails closed — if the chain cannot be read, no deed is accepted.
Ordering is load-bearing: a token that's the wrong version, wrong audience/tenant, wrong/replayed challenge, expired, unparseable, or carrying a bad proof fails before either chain read, so most rejections cost zero RPC calls. See Sovereign tier § What the verifier checks for the exact order.
The operator's own origin-vouch self-check (boot-time, not caller-facing)#
These three codes are not returned while verifying a caller's deed — they come only from DeedGuard::verify_own_origin_vouch / verifyOwnOriginVouchAt, the DX check an RP calls once at boot to catch its own misconfigured vouch before it causes a stream of failed logins. See Sovereign tier § Origin provenance.
| Code | When it happens |
|---|---|
OriginVouchExpired | This guard's own origin vouch is past its exp. Checked before any chain read. |
OriginVouchTtlExceeded | This guard's own vouch has an exp further out than the maximum accepted TTL (90 days). Checked before any chain read. |
BadOriginVouch | The vouch signature is malformed, or the chain says the recovered signer is not a current voucher for this tenant/epoch. |
See also#
- Verify a deed — the relying-party side.
- Wallet login and Agent tokens — the flows that produce the deeds these errors are about.
- Sovereign tier — the full reference, including exact verification order.
../llms-full.txt— the entire product in one file.