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

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.

Generic / opaque failures (HTTP 500, no clear cause)

A bad_request gives you a substring to match on. A bare HTTP 500 with no further detail is a different situation — it usually isn’t your contract logic. Before assuming it’s a bug in your code, check these in order:
  1. Grab the request_id. Most 500 responses still include one — save it before you start changing code. If you end up asking for help, it’s the single most useful thing you can hand over.
  2. Re-check egress and ACLs first. A missing outbound-host grant or a missing map ACL entry can surface as a 500 instead of the more specific error you’d expect — re-read the egress and map ACL requirements before looking further.
  3. Retry once, deliberately. A single unhealthy node can return a 500 for requests that are otherwise correct. If an identical request succeeds on retry, it was very likely transient — no code change needed.
  4. If it’s consistent and reproducible, it’s more likely a platform-side issue than your integration. Report it in the developer Telegram with the request_id, rather than spending hours guessing at workarounds.

Common integration gotchas

These aren’t errors with a fixed message — they’re patterns that produce confusing behavior downstream, reported independently by multiple teams.

Authentication & wallet linking

These come from the user/session contract during sign-in and addAuthMethod, with the code at the front of detail: