Skip to main content
Every failed request returns a JSON-RPC 2.0 error object, whether the call was made over WebSocket or HTTP POST. The error object always has three fields:
integer
required
The numeric error code. Negative codes are JSON-RPC / transport-level; positive codes are Derive application errors (see the catalog below).
string
required
A short, stable human-readable summary.
string | null
required
Optional detail (e.g. the offending field or protocol reason). Always present on the wire — it is null when there is no detail.

JSON-RPC base codes

The standard JSON-RPC 2.0 codes cover malformed or unroutable requests before any application logic runs.
Internal errors are redacted. For code −32603, the server always returns message: "Internal error" and data: null on the wire — any underlying detail is kept server-side and never leaked to clients. Treat −32603 as “retry or contact support,” not as a description of what went wrong.

Transport & session codes

See Rate limits for how the two-tier limiter works and how to read your live limits, and Authentication for the session-login and action-signing layers behind the 401/403 and 14xxx codes.

Application error catalog

Application errors use positive codes grouped by numeric range. Codes are stable; gaps within a range are reserved.
Internal 8xxx codes (e.g. counterparty/feed diagnostics) are intentionally omitted from this reference — they are server-side signals, not client-actionable, and are excluded from public docs.

9xxx — Confirmation timeouts and backend availability

For 9000 and 9001 the order was accepted but a downstream confirmation did not arrive in time; query order state before resubmitting. 9002 and 9003 are different: the request never took effect, so it is safe to retry as-is.

10xxx — Accounts, transfers & margin

Rejections from account, session-key, and subaccount-level constraints before an order reaches the book.

11000–11039 — Orders, balances & matching

Order-lifecycle rejections from the matching engine, plus the balance-level guards that reject a debit before it is applied.

11050–11055 — Trigger orders

Stop / trigger-order specific rejections.
A trigger order can also fail after it triggers. That failure is not a JSON-RPC error, so it carries no code. The order’s trigger_reject_message field, in order responses and order history, gives the reason.

11100–11113 — RFQs & quotes

Request-for-quote and quote-matching rejections.

12xxx — Market data

13000 — Subscriptions

14xxx — Authentication & authorization

Session-login, signature, and session-key scope failures. See Authentication for the underlying scheme.
14014 with signing that looks right is usually bad ABI encoding, not a bad signature. Routes encode Action.data server-side, so your bytes never reach the decoder — the hashes simply disagree, naming no field.Send them to public/decode_action (no auth, executes nothing) for the decoded fields or the exact fault:
SDK: await client.decodeAction('order', encodedData). Once the bytes decode, the *_debug routes compare EIP-712 hashes.

16xxx — Compliance

17xxx — Risk universes

18xxx — Vaults

19xxx — Liquidations

Rejections from private/liquidate, public/margin_watch and private/get_margin. data carries the specifics, such as the actual price and the limit for 19007.

Handling errors

Branch on code for programmatic handling and surface message (and data when present) to users. Never parse message text — it is stable but treat code as the contract. For −32603, retry with backoff rather than inspecting the (redacted) body.