Skip to content

Error Codes

Every Router error uses the same OpenAI-compatible shape. error.type puts the failure in a bucket, error.code says exactly what happened, and request_id identifies the request — quote it in any support request.

{
"error": {
"message": "Insufficient balance to process request",
"type": "payment_error",
"code": "insufficient_balance"
},
"request_id": "<REQUEST_ID>"
}

Branch on error.code, not on error.message. Messages are human-readable and may be reworded; codes are the contract.

Status Meaning
400 Bad request — malformed body, unsupported capability, or a bad routing header
401 Missing or invalid authentication
402 Insufficient balance
403 The credential is not permitted to perform this action
404 Resource not found
429 Rate limited — read Retry-After
502 The provider returned an error and failover was exhausted
503 No healthy provider available for the request
type code Status When it happens
invalid_request_error invalid_body 400 The request body is malformed or violates the schema
invalid_request_error invalid_provider_header 400 An X-0G-Provider-* header has a value outside its domain, such as Sort: fastest or Allow-Fallbacks: 1
invalid_request_error invalid_trust_mode 400 X-0G-Provider-Trust-Mode is not standard, verified, or private
invalid_request_error invalid_max_price_usd 400 A Max-Price-Usd-* value is not a finite, non-negative decimal
invalid_request_error no_provider_within_max_price 400 The price ceiling filtered out every candidate
invalid_request_error pinned_provider_exceeds_max_price 400 The pinned provider address is priced above the ceiling
invalid_request_error model_not_capable 400 Require-Parameters: true and no provider supports the requested parameters
invalid_request_error no_provider_within_max_tokens 400 Require-Parameters: true and no provider advertises enough output capacity
invalid_request_error missing_authorization 401 No Authorization header
invalid_request_error invalid_api_key 401 The key does not exist or is malformed
permission_error trust_mode_mismatch 403 A request header asked for a different trust mode than the key enforces
payment_error insufficient_balance 402 Not enough 0G deposited to cover the request
permission_error access_denied 403 The credential is not allowed to perform this action
permission_error insufficient_scope 403 The credential lacks the required scope, most often a sk- key calling /v1/account/*
not_found_error api_key_not_found 404 The referenced key does not exist
rate_limit_error rate_limit_exceeded 429 Over the request limit; read Retry-After
server_error provider_error 502 The provider failed and every healthy candidate had been tried
server_error no_available_provider 503 No healthy provider serves this model right now
server_error no_provider_for_trust_mode 503 No provider in the requested trust tier is available

Every routing code in this table comes from one of the eight X-0G-Provider-* headers. See Provider Routing Headers for the semantics behind each one.

no_available_provider means the model has no healthy capacity at all. no_provider_for_trust_mode means capacity exists but not in the tier you asked for; the message names the tier, as in no provider available for trust mode: tier=private. The Router returns this rather than silently serving you from a weaker tier. Either wait, or move to a model with providers in that tier. See Trust Modes.

no_provider_within_max_price looks like a capacity problem but is not. The pool is empty because of a constraint you set, and no amount of waiting changes that: it is structural, not transient. It is a 400 so your retry logic treats it as “fix the request” rather than “try again in a moment.” Same reasoning for pinned_provider_exceeds_max_price.

Status Retry? How
429 Yes Honor Retry-After, in seconds. Never retry in a tight loop — read X-RateLimit-Remaining-Requests and slow down before you get here.
502 Yes, briefly Failover already tried every healthy provider, but one may have just come back. Retry with backoff and give up after a small number of attempts.
503 Not immediately Unlikely to resolve in seconds. Switch models or wait; do not hammer.
400 No The request is wrong. Retrying it unchanged produces the same error.
401 No Fix the credential.
402 No Add funds; retrying cannot create balance. See Get 0G and fund your account.
403 No Use a credential with the right scope.

The rule of thumb: 4xx means change something before you retry, 5xx means the request was fine and the network was not. The exception that catches people is no_provider_within_max_price, a 4xx that reads like a capacity error. It is still a 4xx: raise the ceiling or drop it.

403 insufficient_scope on an account endpoint. You are using a sk- key. Inference keys can no longer read /v1/account/*; that requires an mk- key with account:read. See API & Authentication.

400 invalid_provider_header on a header you believe is fine. Check case and type. Sort must be exactly latency or price, lowercase. The boolean headers accept only true or false, case-insensitively, so 1 and yes are rejected.

401 invalid_api_key from a deployment that was working. A revoked key returns the same code as an unknown one. Revocation is immediate, with no grace period, so roll the new key everywhere before revoking the old.

A 400 on a header you meant to leave unset. Absent and blank headers are always treated as unset and never error, so this means something in your stack is emitting a real, malformed value.

402 insufficient_balance mid-job. Balance is drawn down per request. Top up before long batch runs — see Get 0G and fund your account.