Reference
Errors
The exact response body for every status, which ones are worth retrying, and how to report one so it can be looked up.
Every error from /v1 has the same shape, which is OpenAI’s:
{
"error": {
"message": "Insufficient balance: $0.001230 required, $0.000400 available",
"type": "insufficient_quota",
"param": null,
"code": "INSUFFICIENT_BALANCE",
"details": {
"required_micros": 1230,
"required_usd": 0.00123,
"available_micros": 400,
"available_usd": 0.0004
}
}
}
message is written to be read by a person. type is OpenAI’s vocabulary, which is what the SDKs
branch on. code is ours, stable, and safe to switch on. param names the offending field when
there is one. details is additive and only present where there is something useful to add.
Every status
| Status | type | What it means | Retry? |
|---|---|---|---|
400 | invalid_request_error | The model does not support a parameter you sent, or you combined Idempotency-Key with stream: true. The message names it | No |
401 | authentication_error | Key missing, malformed or revoked. Also carries WWW-Authenticate | No |
402 | insufficient_quota | Not enough balance. details says how much was needed and how much you had | After topping up |
403 | permission_error | The model exists but its licence forbids commercial use, so nobody can serve it. Pick another from GET /v1/models | No |
404 | not_found_error | No such model. GET /v1/models has the list | No |
409 | invalid_request_error | An identical Idempotency-Key is still in flight. Wait and retry | Yes, shortly |
422 | invalid_request_error | The body failed validation, or an Idempotency-Key was reused with a different body. details has the field errors | No |
429 | rate_limit_error | Over the limit. Retry-After says when | Yes, after waiting |
500 | api_error | Our fault. request_id is in the body; quote it | Yes, with backoff |
502 | api_error | The upstream model failed. You are not charged. Usually transient | Yes, with backoff |
Reading one
import openai
try:
reply = client.chat.completions.create(model="llama-3.1-8b", messages=messages)
except openai.APIStatusError as e:
print(e.status_code) # 402
print(e.message) # "Insufficient balance: $0.001230 required, …"
print(e.body["error"]["type"]) # "insufficient_quota"
print(e.response.headers["x-request-id"])import OpenAI from "openai";
try {
await client.chat.completions.create({ model: "llama-3.1-8b", messages });
} catch (err) {
if (err instanceof OpenAI.APIError) {
console.log(err.status, err.message, err.type, err.headers["x-request-id"]);
}
}Report an error
Every response carries x-request-id, and /v1/chat/completions also returns it as
dawnstack.request_id in the body. Quote it. See Request ids.
A note on the dashboard surface
/api/v1/* uses a different envelope, {"ok": false, "error": {...}}. That is the dashboard’s own
contract, it is not part of the public API, and you should not write against it.