Error envelope

Every Cloven error response, on every surface, follows one shape. Branch on code, surface message to humans, log requestId for support.

{
  "error": {
    "code": "pack_access_denied",
    "message": "your key does not have access to pack 'ai'; upgrade to unlock all packs",
    "requestId": "req_01HXY8AB..."
  }
}

The MCP surface wraps the same payload inside the tool error contract:

{
  "isError": true,
  "content": [
    { "type": "text", "text": "pack_access_denied: your key does not have access to pack 'ai'..." }
  ]
}

The SDK throws a typed ClovenApiError carrying code, message, requestId, and status.

Status codes

StatusCodeCauseResolution
400missing_query/v1/search called without qSupply a non-empty q param.
400missing_at/v1/snapshot called without atSupply an ISO8601 at.
400invalid_atat is not a parseable ISO8601Use new Date().toISOString() or equivalent.
400missing_ref/v1/cite called without refSupply integer ref ≥ 1.
400invalid_refref is not a positive integerSupply integer ref ≥ 1.
400invalid_payment_headerx-402-payment header malformedRe-encode the proof; confirm base64 JSON.
400wrong_networkPayment header declares a network other than robinhoodSettle on Robinhood Chain (id 4663) — the Base rail is retired.
400wrong_schemePayment header scheme is not x402Echo scheme back verbatim from the quote.
400invalid_tx_hashNot a 0x-prefixed 32-byte hex stringPass the raw tx hash from the receipt.
400invalid_payerNot a 0x-prefixed 20-byte addressPass the signing wallet's address.
400tx_not_foundNo receipt for that hash on Robinhood ChainConfirm the tx landed at robinhoodchain.blockscout.com; you may be on the wrong chain.
400tx_revertedTransfer tx reverted on-chainCheck USDG balance and gas (ETH); pay again.
400no_stable_transfer_in_txNo USDG Transfer to the treasury in that receiptConfirm you transferred USDG to the quoted recipient.
400tx_too_oldTx block timestamp > 10 min agoPay a fresh tx.
400insufficient_paymentSummed USDG Transfer value below quoteRe-quote, pay the full amount. No partial credit.
401invalid_tokenBearer/SSE token failed validationRe-issue from /console.
401missing_tokenSSE called without token query paramAdd ?token=cv_….
401key_revokedKey was revoked since last cache refreshIssue a replacement.
402payment_requiredNo auth + no payment proofPay USDG per the x402 spec. Body carries PaymentRequirements.
403pack_access_deniedKey tier doesn't include the requested packUpgrade tier or change pack.
404pack_not_foundUnknown pack idCheck cloven://packs or pack catalog.
404snapshot_not_foundNo snapshot at the requested minuteTry a nearby minute; older snapshots require Pro+.
404citation_not_foundref out of range for this packCheck pack.sources.length.
429quota_exhaustedTier quota exceededWait for window roll or upgrade. Retry-After header included.
500internal_errorUnhandled — engineering pagedRetry with backoff; report requestId.
503state_unavailableFirst pulse hasn't landed (cold pack)Retry in 30s.
503brief_unavailablePack hasn't produced first briefRetry in 60s.

Codes are stable

code values are part of the public contract. They will not change without a major version bump. New codes may be added — branch on known codes, default to "log + retry" for unknown ones.

requestId

Every response — success or error — carries X-Request-Id. On errors it's also inlined into the error envelope. Pass it to support and we can pull the full trace (route, pack, source health snapshot, Groq token counts) in one query.

requestId is a ULID — sortable by creation time, safe to log, safe to surface to end users.

Error voice

Cloven error messages are concrete, technical, and never blame the user when the cause is on our side. Read them — they tell you the fix.

  • Good: "your key does not have access to pack 'ai'; upgrade to unlock all packs".
  • Good: "no snapshot found for pack 'crypto' at 2026-05-23T03:04 (snapshots older than 24h require a Pro+ subscription and Postgres lookup)".
  • Bad (we don't do this): "Error occurred. Please try again.".

If you ever see a vague message, file an issue — that's a bug in our error catalog.

Retries

Cloven endpoints are idempotent (the cite endpoint accepts both GET and POST; POST is for symmetry, not state mutation). Safe to retry on 5xx and 429 with exponential backoff. Do not retry on 400/401/403/404 — those errors indicate a request shape problem that retrying won't fix.

x402 retries are special: a 402 means "pay first, then retry". The SDK handles this transparently in wallet mode. If you're rolling your own client, treat 402 as the start of a payment dance, not as a retry condition.

A 400 with an x402 code means the payment proof you presented was rejected — a 400 is Cloven's answer to "you gave me a header and it doesn't verify", while 402 is "you gave me nothing". Retrying the same header will not help. Read the code (wrong_network, tx_not_found, insufficient_payment, …), fix the cause, and pay fresh.

Rate limit detail

The 429 response carries Retry-After: <seconds> indicating when your quota window rolls. The sliding window is per-key. Multiple keys on the same account each have their own window. Plan around the window if you batch — the cleanest pattern is to back off until Retry-After, then resume at half the previous rate.