BlockRun

Error Handling

BlockRun uses standard HTTP status codes and returns detailed error information.

HTTP Status Codes

CodeMeaning
200Success
400Bad Request - invalid parameters, unknown model, oversized body, or an upstream rejection of one of your parameters (surfaced as 400, never 500)
402Payment Required - sign and retry with payment; or a payment that failed verification (carries a code, see below)
429Rate limited - upstream capacity for that model, or the per-IP free-tier limit; honor Retry-After
503Model unavailable / upstream configuration problem - retry or fail over
500Server Error - something unexpected went wrong
504Upstream timed out (120s) - nothing settled; retry

Error Response Format

Gateway errors use the OpenAI envelope, with message and code mirrored at the top level for older clients. debug appears only when the fault is yours to fix — a 4xx such as an upstream rejecting one of your parameters — and then carries the upstream's description of it, redacted: credentials, URLs, deployment and account identifiers, and any routing infrastructure we do not sell under its own name are removed. A 429 or 5xx never carries upstream text: it describes our capacity or an upstream fault, which you cannot act on, so the body has just code and message (we keep the full text in our logs — quote the x-blockrun-gateway-request-id response header when you report one).

{
  "error": {
    "message": "Invalid request parameter — Message @bc1max on Telegram for help.",
    "type": "invalid_request_error",
    "code": "INVALID_PARAMETER",
    "param": null
  },
  "message": "Message @bc1max on Telegram for help.",
  "code": "INVALID_PARAMETER",
  "debug": "<the upstream's description of the rejected parameter, redacted>"
}

error.type is one of invalid_request_error, rate_limit_error, api_error, payment_required. The Anthropic-compatible /v1/messages endpoint answers in Anthropic's {"type":"error","error":{"type","message"}} shape and /v1/responses in OpenAI's {"error":{"message","type","param","code"}} shape instead.

Error codes

codeStatusMeaning
INVALID_JSON400Body is not valid JSON
INVALID_REQUEST_BODY400Schema validation failed; details lists the offending paths
EMPTY_CONVERSATION400messages had only system entries
INVALID_PARAMETER400Upstream rejected one of your sampling/tool parameters
CONTEXT_LENGTH_EXCEEDED400Prompt does not fit the model's context window
INVALID_IMAGE_URL400An image_url could not be fetched
REQUEST_TOO_LARGE400Body over the size limit
CONTENT_FILTERED400Upstream safety filter blocked the request
STREAM_UNSUPPORTED400stream: true on a model that only serves non-streaming
REASONING_FORMAT_ERROR, TOOL_ID_FORMAT_ERROR, INVALID_REQUEST400Message-history shape problems
PAYMENT_INVALID, PAYMENT_UNFUNDED, PAYMENT_BLOCKHASH_STALE, PAYMENT_REPLAY402Payment verification failed — see below
RATE_LIMITED429Upstream capacity for that model exhausted; Retry-After + X-RateLimit-Source set
FREE_TIER_RATE_LIMITED429Per-IP free-tier limit (30/min, 300/hour)
STREAM_FAILED, FREE_MODEL_FAILED429Free-model capacity exhausted; Retry-After: 30
MODEL_UNAVAILABLE503Upstream reports the model missing, overloaded, or at capacity
PROVIDER_CONFIG_ERROR503Upstream credential/quota problem on our side
TIMEOUT504Upstream did not answer within 120s
INTERNAL_ERROR500Anything unclassified

Errors after a stream has started

Once a stream: true response has begun, the status is already 200, so a failure arrives as a final SSE error event instead. Its message is fixed text ending in a code, never upstream text:

CodeMeaning
(code: deadline)The response ran past the gateway's time limit and was cut off
(code: stall)The upstream stopped sending data and the stream was cut off
(code: rate_limited)The upstream hit its rate limit mid-response; retry shortly
(code: upstream_error)The upstream failed before completing the response
Upstream rejected the request (4xx): …The upstream refused one of your parameters; the redacted reason follows, as with debug above

Billing for a cut-off stream follows the settlement rules for that endpoint: see the X-Payment-* response headers.

Common Errors

400 - Invalid Request

{
  "error": {"message": "Invalid request body", "type": "invalid_request_error", "code": "INVALID_REQUEST_BODY", "param": null},
  "message": "Invalid request body",
  "code": "INVALID_REQUEST_BODY",
  "details": [
    {"path": ["model"], "message": "Required"}
  ]
}

An unknown model is a plain-string error that suggests live IDs:

{"error": "Unknown model: openai/gpt-4. Try one of: openai/gpt-5.6-sol, …. Full list: GET /v1/models"}

Causes:

  • Missing required fields (model, messages)
  • Invalid model ID
  • Malformed JSON
  • A parameter the upstream model rejects (INVALID_PARAMETER) — the gateway surfaces these as 400, not 500

402 - Payment Required

{
  "x402Version": 2,
  "accepts": [{"scheme": "exact", "network": "eip155:8453", "amount": "246850", "asset": "0x8335…", "payTo": "0x…", "maxTimeoutSeconds": 300}],
  "error": "Payment Required",
  "message": "This endpoint requires x402 payment",
  "price": {"amount": "0.246850", "currency": "USD"},
  "paymentInfo": {"network": "base", "asset": "USDC", "x402Version": 2}
}

The signed requirements travel in the X-Payment-Required / PAYMENT-REQUIRED headers (and WWW-Authenticate: X402 requirements="…"), and — since 2026-08-30 — are mirrored at the top level of the JSON body too (x402Version, accepts), byte-identical to the decoded header. This is for v1-era x402 clients (early x402-fetch/x402-axios and third-party wrappers) that only parse the body and silently fail to auto-pay when there's no top-level accepts. price.amount equals the signed amount, including the flat $0.001 transaction fee. On chat, an exact payment is quoted and settled at input plus your full max_tokens as output (8192 when unset); see How the quote is computed.

402 is not an error

A 402 Payment Required is part of the normal x402 flow — the gateway is quoting a price. Sign and retry with payment and the SDKs handle this round-trip automatically.

402 - Payment Rejected

A PAYMENT-SIGNATURE that fails verification is answered with 402 and a machine-readable code (since 2026-08-26, on every BlockRun-native paid endpoint):

{
  "error": "Payment verification failed",
  "code": "PAYMENT_UNFUNDED",
  "message": "The payment authorization could not be executed on-chain. The usual cause is an insufficient USDC balance on Base for the quoted amount — …",
  "debug": "<facilitator reason>",
  "payer": "0x…"
}
codeMeaningFix
PAYMENT_UNFUNDEDTransfer simulation reverted — usually insufficient USDC (an authorization outside its validAfter/validBefore window reverts the same way)Fund the wallet; re-sign if your clock is off
PAYMENT_BLOCKHASH_STALESolana-signed payment pinned to an expired blockhash. Nothing was chargedRe-sign against a current blockhash and resend
PAYMENT_REPLAYThat authorization nonce was already usedSign a fresh authorization per request. (On image endpoints a replay of a paid-but-lost response returns the job you already paid for instead)
PAYMENT_INVALIDAny other verification failure — bad signature, wrong network or asset, malformed payloadSign exactly the requirements from the 402 header

Verification always runs before settlement, so none of these charged you. On the Solana gateway PAYMENT_VERIFICATION_UNAVAILABLE means the facilitator was unreachable — retry the same signed payment.

429 - Rate Limited

{
  "error": {"message": "Rate limited — … retry after 60s, or fail over to a same-tier model on a different provider.", "type": "rate_limit_error", "code": "RATE_LIMITED", "param": null},
  "code": "RATE_LIMITED",
  "source": "openai",
  "retry_after_seconds": 60
}

Headers: Retry-After: 60, X-RateLimit-Source: <model family>. Free models add FREE_TIER_RATE_LIMITED with X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset. See Rate Limits.

503 - Model Unavailable

{
  "error": {"message": "Model unavailable — Message @bc1max on Telegram for help.", "type": "api_error", "code": "MODEL_UNAVAILABLE", "param": null},
  "code": "MODEL_UNAVAILABLE"
}

Retry, or fail over to a same-tier model from a different family. Not settled.

500 - Server Error

{
  "error": {"message": "Unexpected error — Message @bc1max on Telegram for help.", "type": "api_error", "code": "INTERNAL_ERROR", "param": null},
  "message": "Message @bc1max on Telegram for help.",
  "code": "INTERNAL_ERROR"
}

Causes:

  • Unclassified upstream error
  • Temporary service issue

Settlement happens only after a successful upstream response, so a 500/503/504 never charges you.

SDK Error Classes

Troubleshooting

"Payment verification failed"

  1. Read the code: PAYMENT_UNFUNDED → top up USDC on Base (or on Solana for sol.blockrun.ai)
  2. PAYMENT_REPLAY → your client reused a nonce; sign a fresh authorization per request
  3. PAYMENT_BLOCKHASH_STALE → re-sign; the Solana blockhash expired between signing and sending
  4. PAYMENT_INVALID → confirm you signed the exact accepts[0] entry from the header (network, asset, amount, payTo) and that the wallet is on the right network

"Unknown model"

  1. Check the model ID matches exactly (e.g., openai/gpt-5.5)
  2. See available models for valid IDs

"Timeout"

  1. Increase the timeout in client options
  2. Try a faster model (e.g., gpt-5.4-mini instead of a -pro reasoning tier), or lower max_tokens — the gateway's own upstream timeout is 120s per call

"Network error"

  1. Check your internet connection
  2. Verify blockrun.ai/api is accessible

What's next?