Error Handling
BlockRun uses standard HTTP status codes and returns detailed error information.
HTTP Status Codes
| Code | Meaning |
|---|---|
| 200 | Success |
| 400 | Bad Request - invalid parameters, unknown model, oversized body, or an upstream rejection of one of your parameters (surfaced as 400, never 500) |
| 402 | Payment Required - sign and retry with payment; or a payment that failed verification (carries a code, see below) |
| 429 | Rate limited - upstream capacity for that model, or the per-IP free-tier limit; honor Retry-After |
| 503 | Model unavailable / upstream configuration problem - retry or fail over |
| 500 | Server Error - something unexpected went wrong |
| 504 | Upstream 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 carries the upstream text when there is one, redacted: credentials, URLs and any routing infrastructure we do not sell under its own name are removed before the response is sent. The status code and the upstream's own description of the fault survive, so debug stays useful for a bug report — it is just not a verbatim copy.
{
"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": "<upstream error text, 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
code | Status | Meaning |
|---|---|---|
INVALID_JSON | 400 | Body is not valid JSON |
INVALID_REQUEST_BODY | 400 | Schema validation failed; details lists the offending paths |
EMPTY_CONVERSATION | 400 | messages had only system entries |
INVALID_PARAMETER | 400 | Upstream rejected one of your sampling/tool parameters |
CONTEXT_LENGTH_EXCEEDED | 400 | Prompt does not fit the model's context window |
INVALID_IMAGE_URL | 400 | An image_url could not be fetched |
REQUEST_TOO_LARGE | 400 | Body over the size limit |
CONTENT_FILTERED | 400 | Upstream safety filter blocked the request |
STREAM_UNSUPPORTED | 400 | stream: true on a model that only serves non-streaming |
REASONING_FORMAT_ERROR, TOOL_ID_FORMAT_ERROR, INVALID_REQUEST | 400 | Message-history shape problems |
PAYMENT_INVALID, PAYMENT_UNFUNDED, PAYMENT_BLOCKHASH_STALE, PAYMENT_REPLAY | 402 | Payment verification failed — see below |
RATE_LIMITED | 429 | Upstream capacity for that model exhausted; Retry-After + X-RateLimit-Source set |
FREE_TIER_RATE_LIMITED | 429 | Per-IP free-tier limit (30/min, 300/hour) |
STREAM_FAILED, FREE_MODEL_FAILED | 429 | Free-model capacity exhausted; Retry-After: 30 |
MODEL_UNAVAILABLE | 503 | Upstream reports the model missing, overloaded, or at capacity |
PROVIDER_CONFIG_ERROR | 503 | Upstream credential/quota problem on our side |
TIMEOUT | 504 | Upstream did not answer within 120s |
INTERNAL_ERROR | 500 | Anything unclassified |
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": "25685", "asset": "0x8335…", "payTo": "0x…", "maxTimeoutSeconds": 300}],
"error": "Payment Required",
"message": "This endpoint requires x402 payment",
"price": {"amount": "0.025685", "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.
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…"
}
code | Meaning | Fix |
|---|---|---|
PAYMENT_UNFUNDED | Transfer 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_STALE | Solana-signed payment pinned to an expired blockhash. Nothing was charged | Re-sign against a current blockhash and resend |
PAYMENT_REPLAY | That authorization nonce was already used | Sign 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_INVALID | Any other verification failure — bad signature, wrong network or asset, malformed payload | Sign 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",
"debug": "<upstream text>"
}
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",
"debug": "<error text>"
}
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"
- Read the
code:PAYMENT_UNFUNDED→ top up USDC on Base (or on Solana forsol.blockrun.ai) PAYMENT_REPLAY→ your client reused a nonce; sign a fresh authorization per requestPAYMENT_BLOCKHASH_STALE→ re-sign; the Solana blockhash expired between signing and sendingPAYMENT_INVALID→ confirm you signed the exactaccepts[0]entry from the header (network, asset, amount,payTo) and that the wallet is on the right network
"Unknown model"
- Check the model ID matches exactly (e.g.,
openai/gpt-5.5) - See available models for valid IDs
"Timeout"
- Increase the timeout in client options
- Try a faster model (e.g.,
gpt-5.4-miniinstead of a-proreasoning tier), or lowermax_tokens— the gateway's own upstream timeout is 120s per call
"Network error"
- Check your internet connection
- Verify
blockrun.ai/apiis accessible