Errors
What each status code means, what the body carries, and what to do about it.
Every error is a JSON body with a machine-readable type, the status_code, and a message written
for a human:
{
"type": "virtual_key_required",
"status_code": 401,
"error": { "message": "virtual key is required. Provide a virtual key via the x-bf-vk header." }
}Branch on type rather than on the message text, which is wording and can change.
Status codes
| Status | type | Meaning | What to do |
|---|---|---|---|
400 | invalid_request | The body is malformed or a parameter is not valid | Fix the request; retrying will not help |
401 | virtual_key_required | No credential was sent | Add the Authorization header |
401 | access_not_found | The key does not exist or was revoked | Check the key, then rotate if it should be valid |
403 | model_not_allowed | The key is not scoped to that model | Use an allowed model or widen the key's scope |
404 | model_not_found | Unknown model id | Check the id against Models and prices |
413 | context_length_exceeded | Input over the ceiling for that model on your plan | Shorten the input, raise the plan, or send it to the streaming host |
429 | rate_limit_exceeded | Concurrency ceiling reached | Back off with jitter and cap attempts |
429 | budget_exceeded | The key's monthly budget is spent | Raise the budget or use another key |
500 | internal_error | Something failed on our side | Retry with backoff; if it persists, contact us with the request id |
503 | unavailable | Temporarily unable to serve | Retry with backoff |
Retrying
Two categories, and treating them the same is how a small incident becomes a large one:
- Retryable:
429,500,503, and network failures. Back off exponentially with jitter, cap the attempts, and surface the failure if the cap is reached. - Not retryable:
400,401,403,404,413. The request is wrong in a way that will still be wrong on attempt five.
Streaming failures
A stream can fail after it has started. finish_reason tells you whether it ended properly:
finish_reason | Meaning |
|---|---|
stop | The model finished |
length | It hit the output ceiling; the answer is incomplete |
| absent, with a connection error | The stream died mid-answer |
length is not an error the API returns, it is a signal you asked for too few tokens. And a stream
that died mid-answer must be retried as a whole request rather than resumed, because a new generation
is not a continuation of the old one.
Reporting a problem
Include the type, the status code, the timestamp, and the model id. Do not include the key. If the
request is reproducible, a curl with the key replaced by a placeholder is the fastest thing you can
send us.