13Reference
Error codes
Every API error arrives in one format. Build your logic on the HTTP status, the code, and the details fields, and show the message text to a person.
Error format
An error is JSON with an error object of three fields:
- code
- A stable code of the form
ERR_…. Use it to decide what to do. - message
- Text to show to a person. It is in English, and the wording may change: do not parse it in code.
- details
- Specifics: what exactly is wrong and what to fix. The field can be empty.
HTTP/1.1 400 Bad Request { "error": { "code": "ERR_INVALID_REQUEST", "message": "The reference image is no longer available. Upload the file again.", "details": { "reason": "reference_unavailable", "input_index": 0, "retryable": false } } }
A body that is not valid JSON, and a multipart upload without a required field, get a 422 response with a body of the form {"detail": […]}. No money is charged. Do not confuse them with ERR_INPUT_FETCH_FAILED: it also arrives with 422, but in the usual format.
Code reference
You can filter the rows by status and search them by word. 429 and 503 responses contain a Retry-After header in seconds.
| Code | HTTP | What it means and what to do |
|---|---|---|
ERR_INVALID_REQUEST | 400 | The request cannot be processed as it is. Read error.message and error.details, fix the request, and send it again. Nothing is charged. |
ERR_CONTENT_POLICY | 400 | A reserved code. A refusal under the content rules is determined after the request is accepted and arrives as a task with the status failed and failure.code: content_policy. |
ERR_API_KEY_INVALID | 401 | The key is missing or not recognized: details.reason is api_key_missing or api_key_invalid. Check the key, Keys and authentication. |
ERR_INSUFFICIENT_BALANCE | 402 | There is not enough money on the balance, or the monthly limit of the key or account is used up. Balance. |
ERR_ACCOUNT_DISABLED | 403 | The key is valid, but the account is disabled. Contact support. |
ERR_API_SUSPENDED | 403 | The account’s API access is paused. Stop sending requests and contact support; the portal remains available. |
ERR_MODEL_NOT_FOUND | 404 | Your account has no such model. The list is in GET /models. |
ERR_NOT_FOUND | 404 | The task was not found or belongs to another account. Check the id. |
ERR_RATE_LIMIT | 429 | Too many requests, task polling more often than once every 5 seconds, the daily upload limit of a new account, or a block after access errors. Wait Retry-After seconds, Limits. |
ERR_QUOTA_EXCEEDED | 429 | Too many tasks in progress, or the same idempotency key was sent at the same time. Wait, then repeat with the same identifiers. |
ERR_INPUT_FETCH_FAILED | 422 | The reference image could not be downloaded or checked before generation and the charge. Retry only if details.retryable = true; otherwise, replace the reference image. |
ERR_GENERATION_FAILED | 500 | Generation could not be started or completed. The charged amount is refunded automatically. details.reason = pricing_unavailable means the price could not be determined before the charge: try again later. |
ERR_PROVIDER_UNAVAILABLE | 503 | Temporary unavailability. Wait for Retry-After, look at details.reason, and limit the number of retries. |
ERR_INTERNAL | 500, 503 | An internal error, 500 or 503. 500 does not say whether the request was accepted: before retrying, check the task by the same idempotency key. A charge for a request that created nothing is refunded automatically. 503 arrives with Retry-After. |
Access errors
These responses are common to all methods that use a key. Do not repeat the request with the same key: repeated 401 and 403 from one IP address lead to a temporary block (more in Limits). For how to store and change keys, see Keys and authentication.
| What happened | Response | What to do |
|---|---|---|
| There is no key in the request | 401 ERR_API_KEY_INVALID details.reason = api_key_missing; message: “no API key on the request” | Pass the key in the Authorization or X-API-Key |
| The key is not recognized | 401 ERR_API_KEY_INVALID details.reason = api_key_invalid; message: “API key not recognized” | Check that the key was copied in full and has not been revoked in the portal |
| The account is disabled | 403 ERR_ACCOUNT_DISABLED details.reason = account_disabled; message: “this account is disabled” | Stop sending requests and contact support |
| API access is paused | 403 ERR_API_SUSPENDED details.reason = api_suspended; message: “API access is paused for this account by its account manager” | Stop sending requests and contact support; the portal remains available |
Request errors
These refusals arrive before the charge. Generation does not start, and no money is spent.
| What happened | Response | What to do |
|---|---|---|
| The reference image is unavailable | 400 ERR_INVALID_REQUEST details.reason = reference_unavailable, details.input_index is the position of the reference image, counting from zero | Upload the file again and replace the file_id. Repeating with the same file will not help |
| The reference image cannot be downloaded | 422 ERR_INPUT_FETCH_FAILED details.reason = input_fetch_failed, details.retryable | With retryable: true, try again later; otherwise replace the reference image |
| The file format of the reference image is not accepted | 400 ERR_INVALID_REQUEST “Unsupported image format. Supported formats: PNG, JPEG, WebP.” | Re-save it as PNG, JPEG, or WebP, Reference images |
| An empty prompt | 400 ERR_INVALID_REQUEST details.fields: ["prompt"] | Pass a prompt that describes the image, even if you have reference images |
| A mask in the request | 400 ERR_INVALID_REQUEST in details.fields: mask or mask_file_id | Masks are not supported. Pass the source image as a reference and describe the edit in the prompt |
| An impossible resolution or aspect ratio | 400 ERR_INVALID_REQUEST details.supported is the list of allowed values | Choose from the list, Models and parameters |
| No such combination for the account | 400 ERR_INVALID_REQUEST details.reason = provider_policy_no_route | Change the resolution or aspect ratio, or contact support |
Temporary refusals
503 means the request cannot be accepted right now. Look at details.reason:
details.reason | What it means | Money |
|---|---|---|
overloaded | The service is overloaded and the request was not accepted. Try again later | Not charged |
no_provider_enabled | The requested configuration is not available to the account right now. Wait, and contact support if the refusal repeats | Not charged |
provider_unavailable | Generation could not be started | If it was charged, the amount is refunded automatically |
Sometimes 503 ERR_INTERNAL arrives with an empty details: a dependent service is temporarily unavailable. A 5xx alone does not say whether the request was accepted: check the task by the idempotency key.
Waiting and retries
429and503responses containRetry-Afterin seconds. Wait at least that long; when polling tasks, wait at least the larger ofRetry-Afteranddetails.min_interval_seconds.- Retry a limited number of times and add a small random delay so that your processes do not hit the API at the same moment.
- Do not repeat
400,401,402,403, and404unchanged: fix the cause first. - If the response was lost, the request returned
500, or it timed out, do not create a new task: repeat the same request with the same idempotency key (Idempotency).
Generation is paid for in advance, and on failure the money is returned automatically. An error response does not confirm the refund: you can see the amount on your balance and in the transaction history in the portal.
Errors after a task is accepted
If the request is accepted (202) and the image fails, it is not an HTTP error. GET /creations/ returns 200 with the status failed and an error string. The amount is refunded to the balance automatically.
"The image or prompt was rejected by the safety filter. Try a different image or rephrase the prompt." "The source image was rejected. Try a different photo." "Generation failed. Please try again." "Nothing was rendered for this request. Describe the image you want in the prompt, or attach the source photo it refers to." "Generation timed out." "The reference image is no longer available. Upload the file again." "Could not download the reference image. Please try again later." "The service is temporarily unavailable. Please try again later." "Generation failed."
- A refusal under the content rules: change the prompt or use another image.
- “Nothing was rendered…”: describe the image you want in the prompt, or attach the reference image it refers to.
- “The reference image is no longer available…”: upload the file again and replace the
file_id. - A timeout, temporary unavailability, or a general failure: retry a limited number of times. If the failures repeat, send the task
idto support.
To create a new image on purpose after failed, use a new idempotency key: the old key will not restart the task, and a retry with it returns the saved 202 response with the same id. A new attempt is paid for as usual and refunded if it fails.
Machine-readable failure reason
Since September 24, 2026, a failed task also contains a failure object: in GET /creations/ and in the creation.failed webhook. It is present only with status: "failed", so treat it as optional when you parse the response.
{
"id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"status": "failed",
"error": "The image or prompt was rejected by the safety filter. Try a different image or rephrase the prompt.",
"failure": {
"type": "declined",
"code": "content_policy",
"retryable": false
}
}- declined
- The cause is in the request itself: the prompt, the reference image, or the input data. The same request gives the same result: change it.
- error
- The cause is on the service side. The same request can be sent again if
retryableis notfalse.
| Code | What it means and what to do | Retry |
|---|---|---|
content_policy | The prompt or the reference image was declined under the content rules. Change the prompt or use another image | no |
source_image_rejected | The reference image was declined. Use another photo | no |
no_image_output | The model answered with text instead of an image, for example it described the image in words, or the prompt refers to an image that was not attached. Describe the image you want or attach a photo | no |
reference_unavailable | The reference image is no longer available. Upload it again and replace the file_id | no |
invalid_request | The request cannot be processed as it is, for example the model does not support the chosen aspect ratio. Fix the request | no |
| Code | What it means and what to do | Retry |
|---|---|---|
timeout | Generation time ran out. Retry | yes |
unavailable | The service was temporarily unavailable. Retry later | yes |
reference_fetch_failed | The reference image could not be downloaded. Retry later | yes |
internal | Another failure on the service side. Retry later | yes |
Build your logic on failure.type and failure.code, not on the error text: it is for display, and the wording may change. The list of codes is closed for now, but new ones may appear: handle an unfamiliar code by its failure.type.
A failed request is free: the amount goes straight back to your balance.
This applies to both types: declined and error.
Frequently asked questions
Which errors are final and which should I retry?
429, 503, and 500 (the last one carefully, with the same idempotency key), as well as tasks whose failure.retryable is not false. Fix 4xx errors other than 429 first.Will my money come back if I get an error?
Why is the error text in English?
message field and the error string are the same for all clients and may change. Use the code, the status, and failure for logic, and show your own text to people.What should I do if the error keeps happening?
id or the time of the request. You do not need to send your API key or your prompt.