Skip to content
Book a callStart free

Errors, and what to do

Every error has a stable code. Branch on the code, not the message. This table is built from the API's own code list.

View as Markdown

Every error body is JSON:

{
"error": "Not enough credits.",
"code": "INSUFFICIENT_CREDITS",
"request_id": "req_...",
"needed": 63,
"balance": 12
}
  • code is stable and machine-readable. Branch on it. Accept a code you do not know and treat it by its HTTP status.
  • request_id is also the X-Request-Id header. Quote it when you ask diffusr for help. Send your own X-Request-Id (1 to 64 letters, digits, _ or -) to choose it.
  • Some codes add detail: issues (VALIDATION_FAILED, PREFLIGHT_FAILED), needed and balance, budget, scope, limit, retry_after_seconds, field, index.
  • 429 and 503 answers carry a Retry-After header: seconds to wait.
  • A refused request is never charged.
  • MCP tool errors start with [CODE] and end with a request_id: line.
CodeHTTPWhat it meansRetry?What to do
UNAUTHORIZED401Missing, malformed or unknown API key.NoSend Authorization: Bearer <key>. Copy the key again from Developers in the app.
KEY_REVOKED401This key was revoked. Make a new one on the Developers page.NoMake a new key on the Developers page and use that.
KEY_EXPIRED401This key passed its expiry date. Make a new one.NoMake a new key on the Developers page.
SCOPE_DENIED403The key does not have the scope this call needs.NoUse a key that has the scope the route names, or make a new key with it.
MODEL_NOT_ALLOWED403The key is limited to other models.NoPass a model the key may use (the default model counts), or use another key.
TEST_MODE_UNSUPPORTED403This call is not available with a test key.NoUse a live key for this call.
ACCOUNT_BLOCKED403The account is blocked. Contact support.NoStop. Tell the user to contact diffusr.
FORBIDDEN403Not allowed (a refusal that has no more specific code).NoRead error for the reason. Do not retry as is.
VALIDATION_FAILED422The input did not match the schema; issues lists each field and why. Nothing was made, nothing charged.NoRead issues: each has a field path and a reason. Fix those fields and send again. Nothing was charged.
INVALID_JSON422The body was not a JSON object.NoSend a JSON object with Content-Type: application/json.
INVALID_REQUEST400 or 422The request was understood but cannot be done as sent (a refusal that has no more specific code).NoRead error, change the request, send again.
PREFLIGHT_FAILED422The job cannot run as described (for example a missing input); issues lists why. Nothing was charged.NoRead issues for what is missing or unusable, fix it, send again. Nothing was charged.
CALLBACK_URL_INVALID422callback_url is not usable: it must be a public https address with no password.NoUse a public https:// address with no username or password.
CALLBACK_NOT_RETRYABLE409That callback event can’t be retried now: it was delivered, is still being tried, or is out of manual retries.NoCheck the event in GET /callbacks. Only a FAILED event with manual retries left can be retried.
REFERENCE_UNREACHABLE422A reference file could not be fetched.NoMake the link public and reachable without a login, or upload the file with POST /uploads.
REFERENCE_TOO_LARGE422A reference file is over the model’s size or length limit.NoSend a smaller or shorter file. Limits are on the Uploads and media page.
REFERENCE_UNSUPPORTED422A reference file is the wrong kind for this model.NoSend the right kind of file: a picture for image_urls, audio for audio_urls, video for video_url.
REFERENCE_FORBIDDEN403A reference points at a file the caller may not use.NoUse a link to your own upload or result, or any public link. Do not use asset:// links.
NOT_FOUND404No such id, or it belongs to someone else (or to the other key mode: test vs live).NoCheck the id. A test key cannot see live results, and a live key cannot see test results.
IDEMPOTENCY_CONFLICT409This Idempotency-Key was already used for a different request.NoUse a new Idempotency-Key for a different request. Reuse the old key only to repeat the exact same request.
CONFLICT409The request conflicts with the current state (a refusal that has no more specific code).NoRead error, fetch the current state, then decide.
INSUFFICIENT_CREDITS402Not enough free credits; needed and balance say by how much.NoTell the user. needed and balance say how short they are. They can top up in the app.
allowance_exceeded402A team member’s limit or the team pot is used up (legacy lowercase code, kept for existing clients).NoTell the user. A team limit is used up.
BUDGET_EXCEEDED402The key’s or account’s daily or monthly API budget would be passed; budget has the window and when it frees up.NoTell the user. budget.resets_at says when the window frees up. Do not retry before then.
RATE_LIMITED429Too many requests of this kind this minute.After Retry-AfterWait Retry-After seconds, then send the same request again (same Idempotency-Key).
CONCURRENCY_LIMIT429Too many jobs queued or running for this key or account.After Retry-AfterWait Retry-After seconds, or wait for a running job to finish. The request was refused, not queued.
PROVIDER_BUSY503Our capacity at the model’s supplier is full. Not the caller’s fault; try again.After Retry-AfterWait Retry-After seconds, then retry. Not your fault; nothing was charged.
AUTH_RATE_LIMITED429Too many failed sign-in attempts from this address.After Retry-AfterStop sending bad keys. Wait Retry-After seconds.
KEY_LIMIT429The key hit its own limit (for example how many keys an account may hold).After Retry-AfterRevoke keys you do not use, or wait Retry-After seconds before making more.
TEST_LIMIT429A test key hit its own cap (per minute or per day). Wait, or use a live key.After Retry-AfterWait Retry-After seconds, or use a live key.
UPLOAD_QUOTA429Too many uploads in the last 24 hours.After Retry-AfterWait Retry-After seconds. Reuse a file_url you already have instead of uploading again.
STORAGE_QUOTA413The account’s stored upload bytes are at the cap; uploads clear on their own.After Retry-AfterWait: uploads clear on their own after their retention time.
TOO_LARGE413The request or file is too large (a refusal that has no more specific code).NoSend a smaller request or file.
WALLET_BUSY503The wallet was locked by another request. Retry at once.Yes, at onceRetry at once with the same Idempotency-Key (Retry-After is 2 seconds).
API_PAUSED503New API starts are paused for everyone. Runs already started finish.After Retry-AfterNew starts are paused. Wait Retry-After seconds. Dry runs still answer.
MODEL_PAUSED503This model is paused for new API starts.After Retry-AfterUse another model, or wait Retry-After seconds.
PROVIDER_PAUSED503This model’s supplier is paused for new API starts.After Retry-AfterUse another model, or wait Retry-After seconds.
UNAVAILABLE503A service we depend on is not available right now (a refusal that has no more specific code). Retry later.After Retry-AfterWait Retry-After seconds if present (else a minute), then retry with the same Idempotency-Key.
INTERNAL_ERROR500Something went wrong on our side. Quote the request_id to support.After Retry-AfterRetry once with the same Idempotency-Key. If it keeps failing, quote request_id to diffusr.

Retry only the codes marked “After Retry-After” or “Yes, at once”, and always with the same Idempotency-Key. If the first try had already been accepted you get that job back (idempotent_replay: true) and are not charged twice.