Error reference for every endpoint and tool
Decode any Flux error: the error shape each endpoint and tool uses, every ability error code with what it means, whether to retry, and where the fix is.
Every Flux error starts with an HTTP status, and most carry a machine-readable code. The abilities grew up one at a time, so today the code does not always sit in the same place: this page shows each shape, then lists every ability code in one table.
For chat and the money checks (every 402 refusal on a model call), see the chat error reference. This page covers the abilities and the two MCP servers, and links back there for chat.
Read the status first
| Status | Means | Retry? |
|---|---|---|
| 400 | The request was refused as it stands. | No: fix the request |
| 401 | The key is missing or not accepted, or the key is not allowed this ability's model. | No: fix the key |
| 402 | A plan or money check refused the call. Nothing was charged. | No: read the code |
| 403 | This key or account may not use this model or ability. | No |
| 404 | The ability is not switched on for your account yet. | No |
| 413 | The input is too large. | No: send less |
| 422 | The request is well formed but its content was refused. | No: fix the request |
| 429 | Too many calls, or a shared budget is used up. | Yes, after a wait |
| 502, 503, 504 | A temporary fault behind the gateway. | Yes, with backoff |
| 529 | The service behind the gateway is at capacity. | Yes, with backoff |
The tools server is the exception: it answers with HTTP 200 and puts the refusal inside the tool result. See Tools server results.
The error shapes
Chat
Chat and model calls use the OpenAI error shape. The code is at error.code, and 402 refusals carry their reason in a header or at error.provider_specific_fields.error, as the 402 section explains.
{"error": {"message": "Flux Router error: ...", "type": "invalid_request_error", "param": null, "code": "invalid_api_key"}}
Ability endpoints
Speech to text, text to speech, the voice list, search, images and decision mode use the same outer shape. The code is at error.code, and param names the field at fault when there is one. Some 400s carry only param and no code.
{"error": {"message": "unsupported or unrecognized audio format", "type": "invalid_request_error", "code": "unsupported_file_format", "param": "file"}}
Images, when a credit check blocks the call
The image endpoints wrap a balance or spend-cap refusal one level deeper, under detail. The code is one of the balance codes from the 402 section, such as credit_exhausted or daily_cap.
{"detail": {"error": {"code": "credit_exhausted", "message": "..."}}}
Page reading
POST /v1/fetch returns a flat shape. The code is the error string itself, and message, when present, explains it.
{"error": "social_blocked", "message": "social-media mass-scrape is not supported"}
Tools server results
The Flux tools server (/mcp-tools/) never answers a tool call with a protocol error. A refusal is a normal tool result whose structured content carries the code:
{
"error": "rate_limited",
"capability": "apps",
"message": "Connected apps is busy for this account right now. Wait a moment, then retry.",
"retryable": true,
"retry_after_seconds": 30
}
retryabletells your agent whether trying again can help.retry_after_secondsappears on somerate_limitedanswers.upgrade_urlappears onpremium_lockedandpayment_required.
Apps are reached only through the tools server, so every apps error arrives in this shape.
Routing server
The routing server (/mcp) speaks JSON-RPC, so its errors are JSON-RPC errors with a numeric code:
{"jsonrpc": "2.0", "id": 1, "error": {"code": -32002, "message": "..."}}
| Code | Meaning |
|---|---|
-32700 | The body is not valid JSON. |
-32600 | The JSON is not a valid request. |
-32601 | Unknown method. |
-32602 | Invalid arguments. |
-32603 | Internal error. Retry. |
-32001 | A required header did not match. |
-32002 | The key is missing or not accepted. |
-32003 | Rate limited. Retry after a wait. |
-32004 | The call needs a session: send initialize first and pass MCP-Session-Id. |
-32005 | The session has expired. Start a new one with initialize. |
Reading the code in one place
This reads the code from any of the HTTP shapes above:
async function fluxErrorCode(res: Response): Promise<string | null> {
const hold = res.headers.get('X-Flux-Hold-Reason');
if (hold) return hold;
const body = await res.json().catch(() => null);
if (!body) return null;
if (typeof body.error === 'string') return body.error; // page reading
const err = body.error ?? body.detail?.error; // abilities, chat, image credit
return err?.provider_specific_fields?.error ?? err?.code ?? null;
}
Every ability code
| Status | Code | Where | What it means | Retry? | Fix |
|---|---|---|---|---|---|
| 400 | (none, param set) | Speech to text, text to speech | A field is invalid, for example stream on transcription or an srt format. | No | Speech to text, text to speech |
| 400 | unsupported_file_format | Speech to text | The file is not audio Flux recognises. The format is read from the file, not its name. | No | Speech to text |
| 400 | invalid_request_error | Text to speech | The speech service refused the request after it passed Flux's own checks. A voice, format or speed that does not suit the model is a 400 with param set and no code instead. | No: change the text or voice | Text to speech |
| 400 | edit_unsupported | Images | This image model cannot edit. | No | Images |
| 400 | invalid_reference_image | Images | A reference image is the wrong type or too large. | No | Images |
| 400 | moderation_blocked | Images | The prompt or image was refused by moderation. | No | Images |
| 400 | social_blocked | Page reading | Major social networks are not read. | No | Read a page |
| 400 | blocked target | Page reading | The URL points at a private or internal address. | No | Read a page |
| 400 | url required, body must be JSON | Page reading | The request body is missing its url, or is not JSON. | No | Read a page |
| 401 | unauthorized | Page reading | The key was not accepted. | No | Read a page |
| 401, 403 | permission_error | Images | The key is not accepted, or is not allowed this image model. | No | Images |
| 402 | premium_locked | Speech, transcription, search, images, tools | The ability needs a paid plan with a cleared payment. Nothing was charged. | No | Plans |
| 402 | upgrade_required | Page reading | The same as premium_locked, in the page-reading shape. | No | Plans |
| 402 | payment_required | Tools, apps | The balance or the free allowance has run out, or (web_fetch on a Free plan) a paid plan is needed. | No | App problems |
| 402 | credit_unresolved | Speech, transcription, search, page reading, images | Your balance could not be checked just now. | Yes, once | Chat error reference |
| 402 | credit_exhausted, daily_cap, monthly_cap | Speech, transcription, search, images, page reading | Your balance, or a spend cap you set, would be passed. The same codes as chat. | No | Chat error reference |
| 402 | price_exceeds_max_price | Images | The image would cost more than your max_price. You were not charged. | No: raise max_price | Images |
| 403 | organization_must_be_verified | Images | This image model is not available to your account right now. | No: pick another model | Images |
| 404 | (none) | Any ability endpoint | The ability is not switched on for your account yet. | No | Abilities |
| 413 | file_too_large | Speech to text | The audio is over the size limit. | No | Speech to text |
| 413 | (none) | Second opinion | The request is too large to check. | No | Second opinion |
| 429 | rate_limit_error | Speech to text, text to speech, search | The per-account rate or audio budget is used up. | Yes, after a wait | Abilities |
| 502, 504 | capability_unavailable | Speech, transcription, search, images, page reading | A temporary fault behind the gateway. | Yes | Retry with backoff |
| 502 | upstream_error, upstream_incomplete, upstream_empty, usage_unavailable, settlement_unavailable | Search | The search did not complete. | Yes | Search |
| 502 | provider failed | Page reading | The page could not be read. | Yes, once | Read a page |
| 503 | capability_unavailable | Page reading | Rendering is unavailable for a while. | Yes | Retry with backoff, or drop render |
| 503 | (none) | Second opinion | Too many checks are running at once. | Yes, after Retry-After | Second opinion |
Tools server codes
error | What it means | Retry? | Fix |
|---|---|---|---|
ability_disabled | Not switched on for your account yet. | No | Carry on without the tool |
premium_locked | Needs a paid, cleared plan. The tool can drop out of your agent's list after this. | No | Plans |
payment_required | Balance or free allowance used up. | No | Billing |
auth_failed | The key on the server entry was not accepted. | No | Tools server |
rate_limited | Too many calls. May carry retry_after_seconds. | Yes | Wait, then retry |
capability_unavailable | A temporary fault. | Yes | Retry shortly |
invalid_request | The input was refused. | No | Fix the input |
too_large | The input is over the tool's limit. | No | Send less |
forbidden | This key may not use the ability. | No | Tools server |
apps_error | Finding or running an app action failed on the app side. | Once | App problems |
Decision mode
POST /v1/decide (and /v1/systemone) uses the ability-endpoint shape: the code is at error.code, and param names the request field at fault (model, state, questions, images or body), never a value. The message is fixed text: it never repeats your state, instructions, option text, question ids or images. Request details are on the decision mode reference.
| Status | Code | What it means | Retry? | Fix |
|---|---|---|---|---|
| 401 | invalid_api_key | The key is missing or not accepted. | No | Check the key |
| 402 | credit_unresolved, or a balance code | Your prepaid credit or a spend cap stopped the call, or your balance could not be checked. | Once, for credit_unresolved | Chat error reference |
| 403 | model_not_allowed | The key is limited to a list of models that does not include flux-decide. | No | Add flux-decide to the key |
| 403 | paid_plan_required | The plan or the key cannot use decision mode. | No | Plans |
| 404 | not_found | Decision mode is not switched on. | No | Abilities |
| 413 | request_too_large | The body is over the size limit. | No | Send less |
| 422 | invalid_request | The body does not match the request shape. | No | Fix the field named by param |
| 422 | model_not_supported | model is missing, or is not flux-decide. | No | Send "model": "flux-decide" |
| 422 | state_too_long | The state is over the token limit. The model would never read the rest, so Flux refuses rather than answer wrongly. | No | Send a shorter state |
| 422 | upstream_rejected | The decision model refused the request, for example an image it could not read. | No | Check the images and questions |
| 429 | rate_limit_exceeded | Too many decisions from your account. | Yes, after Retry-After | Wait, then retry |
| 529 | upstream_overloaded | The decision model is at capacity. | Yes | Retry with backoff |
| 503 | upstream_unavailable | The decision model did not answer in time or could not be reached. | Yes | Retry with backoff |
| 503 | capability_unavailable | Decision mode is temporarily unavailable. | Yes | Retry later |
Nothing is charged for any of these.
premium_locked, payment_required and credit_unresolved
Three 402 codes look alike and need different fixes:
premium_locked(orupgrade_requiredfrom page reading): your plan does not include paid abilities yet. Add a paid plan, or wait for your first payment to clear. Adding credit alone does not help.payment_required: a tool's route asked for payment. Usually the money ran out: your balance, or on apps the free daily runs, so add credit. Theweb_fetchtool also answerspayment_requiredon a Free plan, where the fix is a paid plan, as forpremium_locked.credit_unresolved: nothing is wrong with your account. Flux could not read your balance at that moment, so it refused rather than guess. Retry once; if it keeps happening, contact support.
Getting help
Keep the X-Flux-Request-Id header from the failing response, or the time of a tool call, and contact support. That lets us find the exact request.