Skip to main content
Errors come back as a JSON-RPC bad_request (HTTP 400) with { code: "bad_request", detail, request_id }. The SDK throws with detail — a human-readable message string, not a typed error object. Match on the substring shown below. User-authentication failures additionally carry a machine code at the front of detail (e.g. eth_authenticator_limit: …), so the SDK can branch with a single startsWith.

Tenant operations — register, maps, dispatch

You’ll see in detailCauseFix
version <x> is not higher than current version <y>Re-registering a contract at a version that isn’t greater than the deployed oneBump the version passed to contracts.register
map already existsRe-running maps.create against an already-provisioned tenantIdempotent — safe to ignore on re-runs
map not foundA map tail in kv_store::get / put doesn’t match what maps.create createdMatch the tails exactly between Create tenant KV maps and your Rust
canonical map name invalid: <reason>tail is empty, contains .., or starts with z:Pass only the local tail (e.g. "secrets") — the SDK prefixes z:<tid>:
quota exceeded: <dim> (e.g. quota exceeded: max_contracts)Hit a per-tenant quotaAsk the cluster operator to raise the quota
access denied: <caller> cannot <op> map "<map>"The contract isn’t on the map’s readers / writers ACLtenant.maps.update to add the contract id to readers / writers
tenant is suspendedThe operator suspended your tenantAsk the operator to resume
host/http.egress_denied: host '<host>' is not in the authorised_hosts allowlistThe contract called a host the caller’s agent_auth grant doesn’t authorizeAdd the host to the user’s grant (see Invoke your contract)
Contract-authored errors are whatever your contract returns. The flight example, for instance, surfaces duffel_api_key not found in z:<tid>:secrets — populate it via the tenant SDK when the secrets map wasn’t seeded (see Seed API key into secrets map) — that’s the contract’s own message, not a platform error.

Authentication & wallet linking

These come from the user/session contract during sign-in and addAuthMethod, with the code at the front of detail:
Code (prefix of detail)When
eth_authenticator_limitHit the cap on wallets linked to one DID (e.g. trying to add an 11th)
eth_auth_map_conflictThe wallet is already linked to a different DID — resolve via account merge
email_not_verifiedA profile upsert ran before the email OTP was verified
user_not_foundThe DID has no profile yet
legacy_fieldA pre-2.0.0 dispatch field was sent (e.g. otp_code on user-upsert)