# Errors > Every error zurelay returns, what it means and what to do about it. Source: https://zurelay.com/docs/errors Errors come back as JSON in the format of the endpoint you called, with a message written for people and, on the OpenAI-style endpoints, a stable code for programs. ## The shape OpenAI-style endpoints: ```json { "error": { "message": "This API key can't use `gpt-6-astra`. It's limited to gpt-6-sol. Change that at https://zurelay.com/app/keys.", "type": "permission_error", "param": "model", "code": "model_not_allowed" } } ``` On `/v1/messages` the same errors come in Anthropic’s shape, which has no code: use the HTTP status and `error.type`: `{ "type": "error", "error": { "type": "...", "message": "..." } }`. Every chat, image and video response, error or not, has an `x-request-id` header. ## Codes | Status | Code | What to do | | --- | --- | --- | | 400 | `invalid_request` | Fix the request: the message says what’s wrong and param says where. | | 400 | `unsupported_content` | The model doesn’t read that kind of file. Remove it or pick a model that does. | | 400 | `invalid_url` | A link in the request didn’t download. The message has the status it answered. | | 400 | `invalid_image` | An input image couldn’t be used (type, size or link). | | 400 | `image_not_generated` | The model declined the prompt. Not charged. | | 400 | `context_length_exceeded` | The model says the conversation is too long for it. Shorten it or pick a model with a longer context. | | 401 | `missing_api_key` | Send the key in Authorization or x-api-key. | | 401 | `invalid_api_key` | The key is wrong or revoked. | | 401 | `expired_api_key` | Create a new key. | | 402 | `insufficient_quota` | Add credit under Billing. | | 402 | `key_budget_exceeded` | Raise the key’s monthly budget, or wait for next month. | | 402 | `key_daily_budget_exceeded` | Raise the key’s daily budget, or wait for midnight UTC. | | 403 | `model_not_allowed` | The key isn’t allowed to use this model. | | 403 | `ip_not_allowed` | The key only works from other addresses. | | 404 | `model_not_found` | Check the model ID on the models page. | | 404 | `unknown_url` | No such endpoint. Check the path and the base URL. | | 404 | `video_not_found` | No video with that ID in this workspace. | | 409 | `video_not_ready` | The video isn’t finished: poll it until its status is completed. | | 409 | `video_failed` | The video failed, so there’s nothing to download. Its error says why. | | 410 | `video_expired` | The video was deleted, from the Library or after its 30 days. | | 413 | `too_large` | The request or a file is over the limit. Send big files as links. | | 429 | `rate_limit_exceeded` | Wait for retry-after seconds, then retry. | | 500 | `server_error` | Something went wrong on our side. Retry. | | 502 | `stream_interrupted` | Sent as the last event of a stream that broke off. Not charged; retry. | | 503 | `model_unavailable` | The model is down right now. Retry after retry-after seconds, or turn on smart routing. | | 503 | `storage_unavailable` | An image was made but couldn’t be delivered. Not charged; retry. | | 503 | `service_unavailable` | A brief problem on our side. Retry. | ## Retrying - Retry `429` and `503`, waiting the `retry-after` header’s seconds (or backing off exponentially). - Don’t retry other `4xx` errors unchanged: they’ll fail the same way. - Failed requests are free, so retrying costs nothing until one succeeds. - The official OpenAI and Anthropic SDKs already retry the right errors for you. ## Errors mid-stream Errors a model returns about your request itself (a parameter it doesn’t take, a prompt too long for it) come through with the model’s own message and code, as a 400 or 422. ## Errors mid-stream Once a stream has started, a failure can’t become an HTTP status. You get a final error event instead (in the endpoint’s format) and the stream ends, and the request isn’t charged. This is rare: most problems are caught and retried before the first token.