Skip to main content

Errors

Every error response uses the same envelope:

{
"error": {
"code": "validation_error",
"message": "Unsupported chainId 4242. Supported: 1135, 8453, 56",
"details": [
{ "path": "chainId", "message": "Expected number, received string" }
]
}
}

details is present on validation errors generated from Zod schemas; it contains a list of field-level issues so you can render them inline in a form.

Status code → code mapping

HTTPcodeWhen
400validation_errorRequest body / query / params failed schema validation, OR the request reached an internal validator (e.g. unsupported chainId, malformed address).
401unauthorizedAuthorization: Bearer … missing, malformed, or rejected by Rift.
403forbiddenReserved — none of the current public endpoints use it.
404not_foundResource doesn't exist (e.g. event ID not on this chain).
409conflictReserved.
429rate_limitedReserved.
500internal_errorUnhandled server-side failure. Message is generic — see server logs for details.
502upstream_errorDownstream RPC, pricing engine, or Rift API returned an error. message includes the upstream's reason.
503service_unavailableDownstream is unreachable (network failure, service down).

Typical errors by endpoint

Reads

EndpointLikely errorWhy
Any /v1/hedge/events/:chainId/:id404 not_foundID doesn't exist
Any :chainId path400 validation_error "Unsupported chainId X"Chain ID isn't in the catalog
Any address-shaped path param400 validation_errorDoesn't match ^0x[0-9a-fA-F]{40}$
Any bytes32 path param (proposalId, nonce)400 validation_errorDoesn't match ^0x[0-9a-fA-F]{64}$

Calldata builders

EndpointLikely errorWhy
POST /v1/tx/erc20/approve400 validation_error "amount must be non-negative"Negative amount
POST /v1/tx/hedge/create-event400 validation_errorMissing required field, bad enum value, etc.
POST /v1/tx/governance/diamond-cut400 validation_error "action must be 0/1/2"Bad facet action enum

Broadcast

| POST /v1/tx/broadcast | 400 validation_error | signedTx isn't 0x-hex | | | 502 upstream_error "nonce too low" | RPC rejected the tx |

Pricing

| POST /v1/pricing/quote | 400 validation_error | Engine rejected (e.g. leverage > 100×, unsupported pair) | | | 502 upstream_error | Engine errored internally | | | 503 service_unavailable | Engine unreachable |

async function call(url: string, init?: RequestInit) {
const r = await fetch(url, init);
const body = await r.json();
if (!r.ok) {
const err = body.error;
// err.code is one of the documented codes above
// err.message is safe to surface in a UI
// err.details (if present) is field-level for form rendering
throw Object.assign(new Error(err.message), { code: err.code, status: r.status, details: err.details });
}
return body.data;
}

err.code is the value to switch on for retry / display logic — it's guaranteed stable across versions, unlike the human message.