Errors reference
Every error the inference API returns uses one envelope:
{
"error": {
"type": "invalid_request_error",
"message": "human-readable explanation",
"code": "machine-readable code",
"param": "the offending field, when there is one"
}
}type is one of a small fixed set (authentication_error,
invalid_request_error, not_found, provider_error,
provider_unavailable, internal_server_error).
code is more specific — branch on it in code, show message to
humans. The messages below are the real strings the gateway produces,
not paraphrases.
401 — authentication
You’ll see one of:
{
"error": {
"type": "authentication_error",
"message": "Missing Authorization header",
"code": "authentication_error"
}
}{
"error": {
"type": "authentication_error",
"message": "API key not registered. Please contact support.",
"code": "api_key_not_registered"
}
}Fix: send Authorization: Bearer sk-... with a key from
the dashboard. “Not registered” after
you just created the key usually means a copy-paste truncation —
re-copy the full token.
402 — insufficient credits
{
"error": {
"type": "invalid_request_error",
"message": "Insufficient credits. Balance: $0.0000. Your balance must be above zero to make requests. Please add credits to your account.",
"code": "insufficient_credits"
}
}The balance is checked before the request is forwarded, so a 402 never costs you tokens. Any positive balance admits a request; because usage is settled after the response, a single request can take the balance below zero, and further requests 402 until you top up.
Fix: top up in Credits & billing.
400 — malformed request
Missing or empty messages:
{
"error": {
"type": "invalid_request_error",
"message": "messages field is required and cannot be empty",
"code": "invalid_request_error",
"param": "messages"
}
}A model id that doesn’t match the public shape
({provider}/{creator}/{model}[/{locode}] — see
available models):
{
"error": {
"type": "invalid_request_error",
"message": "model id must be {provider}/{creator}/{model}[/{locode}]: got 5 segments",
"code": "invalid_request_error",
"param": "model"
}
}An alias name that violates the naming rule:
{
"error": {
"type": "invalid_request_error",
"message": "alias name must be 1-64 chars: lowercase a-z, 0-9, '-' or '_', starting with a letter or digit (got \"My Alias\")",
"code": "invalid_alias_name",
"param": "model"
}
}Fix: the message names the field; param confirms it. Compare
against the request shape in
your first completion.
404 — the route doesn’t exist
Unknown model on a provider:
{
"error": {
"type": "not_found",
"message": "model \"anthropic/claude-opus-4.6\" is not offered by provider \"openai\"",
"code": "not_found",
"param": "model"
}
}A model that is only served in specific regions, addressed without a region:
{
"error": {
"type": "not_found",
"message": "model \"anthropic/claude-opus-4.6\" on provider \"vertex\" is served only in specific regions and has no global endpoint — the id is ambiguous without a region. Append a locode (e.g. \"vertex/anthropic/claude-opus-4.6/{locode}\") and check /providers/vertex for available regions",
"code": "not_found",
"param": "model"
}
}An alias that doesn’t exist on your account:
{
"error": {
"type": "not_found",
"message": "alias \"alias/big\" does not exist on this account — create or repoint aliases in the dashboard at /dashboard/aliases",
"code": "alias_not_found",
"param": "model"
}
}Fix: browse the model catalog or
GET /v1/models for exact ids; aliases are per-account, so a key from
another account won’t see yours.
503 — the route exists but can’t serve you right now
A region the model isn’t served in. This is deliberate: we never silently substitute a different region — the region you pin is the region you get, even when a “nearby” one would work:
{
"error": {
"type": "provider_unavailable",
"message": "model \"mistral/mistral-large\" is not served in region \"de-ber\" on provider \"mistral\" — check /providers/mistral for available regions",
"code": "provider_unavailable",
"param": "model"
}
}A model we’ve marked unavailable says so with
"code": "model_unavailable" and names the reason. And when
lowrouter/auto has tried its ranked candidates and every one failed,
the request returns 503 with "type": "provider_unavailable" and
“All providers failed. Last error: …” in message (an explicit model
that fails upstream returns "type": "provider_error" instead) —
lowrouter_metadata.providers_attempted on failed-over responses
shows what was tried.
Fix: pick a served region from /providers/{provider}, or point
an alias at an alternative route so clients don’t
need redeploying when a region is down.
429 — rate limited
The only 429 the gateway itself emits is its per-IP limiter, with a
Retry-After header:
{
"error": {
"type": "invalid_request_error",
"message": "Rate limit exceeded. Too many requests from your IP address. Try again in 30 seconds",
"code": "rate_limit_exceeded"
}
}An upstream provider’s rate limit is not passed through as a 429:
it surfaces as one of the 503 provider failures above (and, with
lowrouter/auto, is retried against the next candidates first).
Fix: honour Retry-After and back off with jitter — or route the
workload across more than one provider, which is rather the point of
a router.
What you’ll never get
No silent substitutions: a failed constraint (region, jurisdiction,
alias) is an error, not a quiet reroute to somewhere you didn’t ask
for. If you got a 2xx, the response’s lowrouter_metadata tells you
exactly who served it and where — see
per-request metadata.