Errors
Every error both APIs return, why it happens, what to do and whether to retry.
Every error carries a stable code. Branch on the code, never on the message: messages may be reworded.
RFS Router
Router errors come in each format's own shape, so the OpenAI and Anthropic SDKs raise them as they would their own. Search by code, status or words.
401invalid_api_keyBad or missing keyFix first
- When
- The key is missing, mistyped, unknown or revoked. A key revoked while a call starts is refused at its reserve.
- What to do
- Send the full router key as
Authorization: Bearer rf_ai_...orx-api-key: rf_ai_.... If it was revoked, make a new one. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "Missing or malformed API key. Send your rf_ai_ key as `Authorization: Bearer <key>` or `x-api-key`.", "type": "authentication_error", "code": "invalid_api_key", "param": null }}{ "type": "error", "error": { "type": "authentication_error", "message": "Missing or malformed API key. Send your rf_ai_ key as `Authorization: Bearer <key>` or `x-api-key`.", "code": "invalid_api_key" }}400invalid_requestBad request bodyFix first
- When
- The body is not JSON, or misses a field the format needs, such as
modelormessages. A model's provider can refuse a parameter the same way. - What to do
- Check the body against the endpoint's reference, and the parameters against the model.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "The request body is not valid JSON.", "type": "invalid_request_error", "code": "invalid_request", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "The request body is not valid JSON.", "code": "invalid_request" }}400unknown_modelUnknown modelFix first
- When
- No listed model has this id. On POST /images, no image model has it.
- What to do
- Copy an id from GET /models or the models page, or from GET /images/models for images. Ids look like
anthropic/claude-sonnet-5.5. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "Unknown model `openai/gpt-9`. Every model we serve is listed at /api/v1/models.", "type": "invalid_request_error", "code": "unknown_model", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "Unknown model `openai/gpt-9`. Every model we serve is listed at /api/v1/models.", "code": "unknown_model" }}400model_not_servedModel not servedFix first
- When
- Free models,
:freeand:batchversions, retired versions and routers that pick a model after the call. Image models billed for something a request can't bound, such as fonts. Their price can't be reserved up front. - What to do
- Use the paid model's own id, or add
:nitro,:floor,:exactoor:onlineto it. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "`meta-llama/llama-5:free` is a free model, and free models are not served here. Every model we serve is listed at /api/v1/models.", "type": "invalid_request_error", "code": "model_not_served", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "`meta-llama/llama-5:free` is a free model, and free models are not served here. Every model we serve is listed at /api/v1/models.", "code": "model_not_served" }}400tool_not_servedTool not servedFix first
- When
- Tools that run other models, or that keep files, memory or a sandbox on a shared account: image generation tools, hosted code execution, file search, memory, X search. Also a tool loop with no step limit.
- What to do
- Remove the tool, or run it on your own machine. Web search and web fetch are served. Set
max_tool_callson tool loops. To make images, call POST /images. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "X search bills for every post it returns, with no limit a request can set, so its cost cannot be reserved up front. Remove `x_search` to search the web only.", "type": "invalid_request_error", "code": "tool_not_served", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "X search bills for every post it returns, with no limit a request can set, so its cost cannot be reserved up front. Remove `x_search` to search the web only.", "code": "tool_not_served" }}400model_no_image_inputModel can't read imagesFix first
- When
- The request carries an image, and neither the model nor any of its fallbacks reads images.
- What to do
- Pick a model whose
architecture.input_modalitiesin GET /models includesimage, or add one as a fallback. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "`z-ai/glm-5.1` does not read images. Send the image to a model that does: GET /api/v1/models lists each model's input modalities.", "type": "invalid_request_error", "code": "model_no_image_input", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "`z-ai/glm-5.1` does not read images. Send the image to a model that does: GET /api/v1/models lists each model's input modalities.", "code": "model_no_image_input" }}400image_type_not_servedImage type not readFix first
- When
- An inline image (a
data:URL or base64 block) is not PNG, JPEG, WebP or GIF, such as HEIC, SVG or TIFF. - What to do
- Convert the image to PNG, JPEG, WebP or GIF, or send it as a link.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "Images are read as PNG, JPEG, WebP or GIF, and this request sends image/heic. Convert it to one of those first.", "type": "invalid_request_error", "code": "image_type_not_served", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "Images are read as PNG, JPEG, WebP or GIF, and this request sends image/heic. Convert it to one of those first.", "code": "image_type_not_served" }}413request_too_largeRequest too largeFix first
- When
- The body is over 4 MB, or the prompt is longer than the model's context.
- What to do
- Send images and files as URLs, not inline base64. Shorten a long conversation, or pick a model with a longer context.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "The request body is larger than 4 MB. Send images and files as URLs instead of inline data.", "type": "invalid_request_error", "code": "request_too_large", "param": null }}{ "type": "error", "error": { "type": "request_too_large", "message": "The request body is larger than 4 MB. Send images and files as URLs instead of inline data.", "code": "request_too_large" }}400request_over_capacityOutput limit too high right nowFix first
- When
- The request asks for more output than the router can hold for a single call right now.
- What to do
- Lower
max_tokens(max_output_tokenson Responses), then send it again. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "This request asks for more output than the gateway can take on right now. Lower max_tokens (max_output_tokens on Responses) and retry.", "type": "invalid_request_error", "code": "request_over_capacity", "param": null }}{ "type": "error", "error": { "type": "invalid_request_error", "message": "This request asks for more output than the gateway can take on right now. Lower max_tokens (max_output_tokens on Responses) and retry.", "code": "request_over_capacity" }}404not_foundPath not servedFix first
- When
- The path doesn't exist, such as embeddings or token counting.
- What to do
- Use one of the endpoints in this reference.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "`POST /v1/embeddings` is not served here. The models are served at /v1/chat/completions, /v1/responses and /v1/messages, and image generation at /v1/images.", "type": "not_found_error", "code": "not_found", "param": null }}{ "type": "error", "error": { "type": "not_found_error", "message": "`POST /v1/embeddings` is not served here. The models are served at /v1/chat/completions, /v1/responses and /v1/messages, and image generation at /v1/images.", "code": "not_found" }}402insufficient_balanceBalance too lowFix first
- When
- What the account can spend now is less than this call's reserve, its worst-case cost. The message names both amounts.
- What to do
- Lower
max_tokensso the reserve fits, wait for running calls to finish, or add credit: the token's payouts add it on their own, and a purchase in USDC adds it at once. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "Balance $0.004210 ($0.001000 held by calls running or being priced) is below this request's reserve of $0.019660. Lower the output limit, or buy credit for this account in USDC.", "type": "billing_error", "code": "insufficient_balance", "param": null }}{ "type": "error", "error": { "type": "billing_error", "message": "Balance $0.004210 ($0.001000 held by calls running or being priced) is below this request's reserve of $0.019660. Lower the output limit, or buy credit for this account in USDC.", "code": "insufficient_balance" }}402key_limitKey's spending limit reachedFix first
- When
- The key's own daily, weekly or monthly limit can't cover this call's reserve. The account's other keys keep working.
- What to do
- Wait for the reset named in the message, lower
max_tokens, or raise the key's limit on the dashboard or withPATCH /keys/{id}. - Retry
- Fix first
- Cost
- Free
{ "error": { "message": "This key's limit of $5.000000 a day is used up: $4.990000 spent and $0.000000 held by calls running or being priced, and this request reserves $0.019660. It resets at 2026-10-01T00:00:00.000Z. Lower the output limit, or ask the account's owner to raise the key's limit.", "type": "billing_error", "code": "key_limit", "param": null }}{ "type": "error", "error": { "type": "billing_error", "message": "This key's limit of $5.000000 a day is used up: $4.990000 spent and $0.000000 held by calls running or being priced, and this request reserves $0.019660. It resets at 2026-10-01T00:00:00.000Z. Lower the output limit, or ask the account's owner to raise the key's limit.", "code": "key_limit" }}429rate_limitedToo fastRetry after the wait
- When
- The account started more than 60 calls at once, or more than 600 a minute.
- What to do
- Wait for Retry-After-Ms and send again. Official OpenAI and Anthropic SDKs do this for you.
- Retry
- Retry after the wait in Retry-After-Ms
- Cost
- Free
{ "error": { "message": "This account is starting calls faster than 600 a minute. Retry in 1 second.", "type": "rate_limit_error", "code": "rate_limited", "param": null }}{ "type": "error", "error": { "type": "rate_limit_error", "message": "This account is starting calls faster than 600 a minute. Retry in 1 second.", "code": "rate_limited" }}429too_many_running_calls8 calls already runningRetry after the wait
- When
- The account has 8 calls running. A slot frees the moment one ends.
- What to do
- Queue calls on your side, or wait the 2 to 8 seconds the headers name.
- Retry
- Retry after the wait in Retry-After-Ms
- Cost
- Free
{ "error": { "message": "This account already has 8 calls running. Retry when one finishes.", "type": "rate_limit_error", "code": "too_many_running_calls", "param": null }}{ "type": "error", "error": { "type": "rate_limit_error", "message": "This account already has 8 calls running. Retry when one finishes.", "code": "too_many_running_calls" }}503/529model_busyModel busyRetry after the wait
- When
- Every provider of this model is at capacity. On /messages it is 529
overloaded_error, which Anthropic's SDKs retry. - What to do
- Wait for Retry-After-Ms, or use another model. Listing fallbacks in
modelslets a call run on the next one. - Retry
- Retry after the wait in Retry-After-Ms
- Cost
- Free
{ "error": { "message": "The model `openai/gpt-6.1` is busy at its providers right now. Retry in 12 seconds.", "type": "server_error", "code": "model_busy", "param": null }}{ "type": "error", "error": { "type": "overloaded_error", "message": "The model `openai/gpt-6.1` is busy at its providers right now. Retry in 12 seconds.", "code": "model_busy" }}503gateway_busyRouter busyRetry after the wait
- When
- The router is at its capacity for a moment.
- What to do
- Wait for Retry-After-Ms and send again.
- Retry
- Retry after the wait in Retry-After-Ms
- Cost
- Free
{ "error": { "message": "The gateway is busy right now. Retry in 8 seconds.", "type": "server_error", "code": "gateway_busy", "param": null }}{ "type": "error", "error": { "type": "overloaded_error", "message": "The gateway is busy right now. Retry in 8 seconds.", "code": "gateway_busy" }}503gateway_capacityOut of capacity brieflyRetry after the wait
- When
- The router is topping up its capacity. We are alerted at once.
- What to do
- Wait for Retry-After-Ms and send again.
- Retry
- Retry after the wait in Retry-After-Ms
- Cost
- Free
{ "error": { "message": "The gateway is briefly out of capacity. Try again soon.", "type": "server_error", "code": "gateway_capacity", "param": null }}{ "type": "error", "error": { "type": "overloaded_error", "message": "The gateway is briefly out of capacity. Try again soon.", "code": "gateway_capacity" }}500gateway_errorRouter failedRetry
- When
- A fault in the router after the reserve. The reserve is released and the call is free.
- What to do
- Send it again. If it keeps failing, write to support@relayfor.si with the
x-relayfor-call-idheader. - Retry
- Retry
- Cost
- Free
{ "error": { "message": "The gateway failed on this call. Retry it.", "type": "server_error", "code": "gateway_error", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The gateway failed on this call. Retry it.", "code": "gateway_error" }}504upstream_timeoutNo answer in timeRetry
- When
- The model sent nothing before the time limit: 30 minutes streamed, 13 minutes not streamed. The call still runs to its end, and is charged what it cost.
- What to do
- Stream long calls, lower
max_tokensor use a faster model. - Retry
- Retry
- Cost
- Only what the provider recorded, usually nothing
{ "error": { "message": "The model did not answer in time.", "type": "server_error", "code": "upstream_timeout", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The model did not answer in time.", "code": "upstream_timeout" }}502upstream_unreachableProvider unreachableRetry
- When
- The connection to the model's provider failed.
- What to do
- Send it again.
- Retry
- Retry
- Cost
- Free
{ "error": { "message": "Could not reach the model provider. Try again.", "type": "server_error", "code": "upstream_unreachable", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "Could not reach the model provider. Try again.", "code": "upstream_unreachable" }}502provider_errorProvider failedRetry
- When
- The model's provider failed, or refused this one call.
- What to do
- Send it again, or use another model.
- Retry
- Retry
- Cost
- Only what the provider recorded, usually nothing
{ "error": { "message": "The model's provider failed to answer. Try again in a moment.", "type": "server_error", "code": "provider_error", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The model's provider failed to answer. Try again in a moment.", "code": "provider_error" }}404no_providerNo provider for this requestFix first
- When
- No provider of the model supports every option in the request, such as tools, images or a long context.
- What to do
- Drop an option, or pick a model that lists it.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "No provider can serve this request with this model. Try another model, or fewer options such as tools or images.", "type": "not_found_error", "code": "no_provider", "param": null }}{ "type": "error", "error": { "type": "not_found_error", "message": "No provider can serve this request with this model. Try another model, or fewer options such as tools or images.", "code": "no_provider" }}403provider_refusedProvider refusedFix first
- When
- The provider's own policy refused the request.
- What to do
- Change the request, or use another model.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "The model's provider refused this request for this model.", "type": "permission_error", "code": "provider_refused", "param": null }}{ "type": "error", "error": { "type": "permission_error", "message": "The model's provider refused this request for this model.", "code": "provider_refused" }}422unprocessableProvider couldn't process itFix first
- When
- The provider accepted the request but couldn't run it.
- What to do
- Check the parameters against the model, or use another model.
- Retry
- Fix first
- Cost
- Free
{ "error": { "message": "The model's provider could not process this request.", "type": "server_error", "code": "unprocessable", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The model's provider could not process this request.", "code": "unprocessable" }}408timeoutProvider timed outRetry
- When
- The provider gave up on the call (408 or 504).
- What to do
- Send it again, stream it or lower
max_tokens. - Retry
- Retry
- Cost
- Only what the provider recorded, usually nothing
{ "error": { "message": "The model took too long to answer. Try again.", "type": "server_error", "code": "timeout", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The model took too long to answer. Try again.", "code": "timeout" }}502upstream_errorOther provider errorRetry
- When
- Any other error from the provider.
- What to do
- Send it again shortly.
- Retry
- Retry
- Cost
- Only what the provider recorded, usually nothing
{ "error": { "message": "The request could not be completed. Try again in a moment.", "type": "server_error", "code": "upstream_error", "param": null }}{ "type": "error", "error": { "type": "api_error", "message": "The request could not be completed. Try again in a moment.", "code": "upstream_error" }}The short version
| Status | Means | Retry? |
|---|---|---|
400 | The request can't be served as sent | No. Fix it first |
401 | The router key is missing, wrong or revoked | No |
402 | The balance or the key's limit can't cover the reserve | No. Lower max_tokens or add credit |
404 | Unknown path, or no provider for this request | No |
413 | The body is over 4 MB | No. Send files as URLs |
429 | Too many running calls, or too fast | Yes, after Retry-After-Ms |
500 | The router failed. The call is free | Yes |
502 504 | The model's provider failed | Yes |
503 529 | Busy for a moment | Yes, after Retry-After-Ms |
Errors inside a stream
Once an answer has started streaming, an error can't change the status any more. It arrives as the format's own error event, so SDKs raise it instead of hanging:
data: {"object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"error"}],"error":{"message":"The model took too long to answer. Try again.","type":"server_error","code":"timeout"}}The call is charged for what was written before the error.
Management API
Every management API error has one shape: { "error": { "code", "message", "param", "request_id" } }, with the HTTP status that fits. param names the field at fault when there is one. Quote request_id if you contact us.
- 400
invalid_requestA field is missing, has the wrong type or breaks a rule.
paramnames it, such assplit.ai_share.What to do: Fix the field the message names, then send again with a new Idempotency-Key.
- 400
missing_idempotency_keyA POST came without an
Idempotency-Keyheader.What to do: Send a unique key with every POST, a UUID.
- 404
not_foundNo launch, token, account, key, preset or webhook with this id in this project, or no such path.
What to do: Check the id. Every id belongs to the project whose key asks.
- 405
method_not_allowedThe path exists, but not for this method: the
Allowheader names the ones it takes.What to do: Send it with a method from
Allow. Each operation's method is in this reference. - 409
idempotency_in_progressA request with the same Idempotency-Key is still running.
What to do: Wait the 2 seconds
Retry-Afternames and send it again: it then gets the first answer. - 409
preset_name_takenThe project has a fee strategy with this name already, whatever the case.
What to do: Pick another name.
- 409
preset_is_defaultThe project's default fee strategy can't be archived.
What to do: Make another strategy the default first.
- 413
payload_too_largeThe body is over 3.5 MB.
What to do: Send a smaller image: up to 2 MB before base64.
- 415
unsupported_media_typeThe body is not JSON.
What to do: Send
Content-Type: application/jsonand a JSON body. - 422
idempotency_mismatchThe Idempotency-Key was used for another body in the last 24 hours.
What to do: Use a new key for a new request.
- 422
too_many_keysThe account has 100 router keys that are not revoked.
What to do: Revoke one you no longer use.
- 422
too_many_webhooksThe project has 5 webhook endpoints.
What to do: Delete one, or send more events to one endpoint.
- 422
too_many_presetsThe project has 20 fee strategies in use.
What to do: Archive one you no longer launch with.
- 422
launch_refusedThe launch can't be built as asked: a route wallet that can't be paid, a split outside the strategy, or a simulation that failed. The message says which.
What to do: Change what the message names, then prepare it again.
- 422
import_refusedThe token can't join a route: not a pump.fun token, its route is locked already, or it pays no creator fee (cashback and holder rewards tokens). The message says which.
What to do: Check the mint. A token whose route is locked can't be brought.
- 422
insufficient_fundsThe signing wallet can't pay: the SOL a launch costs, or the USDC and network fee of a purchase.
What to do: Fund the wallet the message names, then prepare it again.
- 429
rate_limitedMore than 300 requests a minute on this secret key, or more than 10 launches and imports a minute in this project.
What to do: Wait the seconds in
Retry-After. A refused request takes nothing from any window. - 500
internalA fault on our side. Nothing was changed.
What to do: Send it again with the same Idempotency-Key. Quote
request_idif it keeps failing. - 503
launches_closedLaunches are paused for a moment, for example while token images can't be stored.
What to do: Try again later.
- 503
purchases_closedBuying credit is paused for a moment.
What to do: Try again later.
- 503
webhooks_closedAdding webhook endpoints is paused for a moment.
What to do: Try again later.
A request refused for any reason changes nothing, and counts against no limit.
- Unknown paths and methods answer in the same shape. A path the API doesn't have is
404 not_found. A method a path doesn't take is405 method_not_allowed, with anAllowheader naming the ones it does. - A refusal that passes by itself says when.
idempotency_in_progress(409) sendsRetry-After: 2,unavailable(503) sendsRetry-After: 5, andrate_limited(429) sends its own wait. Each operation in this reference lists which of its answers carry it.