Errors
Errors come back as JSON in OpenAI's shape: an error object with a readable message and a stable type your code can branch on.
The format
Branch on the type: it is the stable part. The message is for whoever reads the logs, and stays in English whatever the language of these docs.
{
"error": {
"message": "Insufficient credit balance. Add credit to your account to continue.",
"type": "insufficient_credit"
}
}Statuses and types
| Status | type | Meaning |
|---|---|---|
| 400 | invalid_ | The body is not valid JSON, or a required field is missing: model, input for embeddings, prompt for images — or an image parameter is out of bounds (Images). |
| 401 | invalid_ | No key, a malformed key, or a revoked one. |
| 402 | insufficient_ | Your credit is at zero or below. Add credit to continue. |
| 404 | model_ | Unknown ID, a model Evanesca does not serve, or a model of the wrong kind for this endpoint. GET /models lists the valid ones. |
| 502 | upstream_ | The operator could not be reached, sent an unreadable answer, or turned down Evanesca's own account. Your key is not the problem: retry, and write to us if it lasts. |
| 503 | model_ | The model is temporarily unavailable: paused, or its operator cannot be reached by Evanesca. Retry later, or pick another model from GET /models. |
Operator errors and retries
Other operator errors — a rate limit, an overloaded model, a parameter the operator rejects — reach you with the operator's status and body, as if you had called it directly, with Retry-After when the operator sends one. OpenAI's official SDKs retry 429 and 5xx answers on their own; when the operator turned down Evanesca's own account, the 502 carries x-should-retry: false so they do not retry a call that cannot succeed.
An operator error never sends the call elsewhere: no model has a fallback outside Europe, so you get the error rather than an answer from another place.
Refused image requests
An image request that breaks a limit is refused with 400 invalid_request before any call, and its param field says which — a prompt too long, n outside 1 to 5, a size not in the list… It costs nothing. A model sent to the wrong image endpoint gets 404 model_not_found (every limit).
An empty answer is not an error
With a small max_tokens, a reasoning model can spend its whole budget thinking: the answer comes back with no content and finish_reason "length". It looks empty, but nothing failed. Leave max_tokens out, or allow about 1,000 tokens or more (reasoning models).
Over MCP
Protocol errors come back as JSON-RPC errors. A tool that fails — operator down, credit at zero, a model Evanesca does not serve (the API's model_not_found) — returns a result flagged isError, which the agent can read before deciding what to do. An expired or revoked OAuth token gets HTTP 401 with a WWW-Authenticate header; a tool called without the right it needs returns an error result that names that right (MCP server).