All errors from the API use a consistent JSON envelope matching the OpenAI
error schema, and every error body carries the request id as
error.request_id; API responses also send it in the X-Request-Id
header. Quote it in any support email and we can pull the full trace.
A few responses come from our edge proxy instead and carry no request id:
a 429 or 413 raised at the edge (same JSON shape), and a 502 or 504
HTML page. Retry a 502 with backoff. A 504 means a non-streamed request
produced no output for 5 minutes; that request may still finish and be
billed, so send long generations with stream: true instead of repeating
the same call.
Credit balance or a spend cap is exhausted, or (Student and Developer plans) today's free allowance is used up or not issued yet.
No — top up or raise the cap. Exceptions: daily_allowance_pending clears by itself within a minute, so retry; daily_allowance_exhausted can clear by itself too when your organization turned off paying from its balance after the free allowance and requests still running hold the rest of it (its message says so).
403
permission_error
Authenticated, but not allowed (suspended org, model not enabled, IP blocked, etc.).
No — fix the policy or pick another model.
404
not_found_error
Resource doesn't exist, isn't visible to you, or the endpoint isn't offered (route_not_found).
No.
409
conflict_error
Idempotency or uniqueness collision (e.g. coupon already used).
No — resolve the conflict.
413
invalid_request_error
Request body over the size cap: 32 MiB on /v1/chat/completions, /v1/embeddings, /v1/decisions and /v1/systemone, 10 MiB on every other route. The message states the limit; base64 attachments count at their encoded size. See 413 — request too large.
No — send fewer or shorter messages and tool outputs, or shrink attachments.
422
invalid_request_error
JSON parsed but fields are invalid.
No — fix the request.
429
rate_limit_error
Per-key RPM ceiling hit (Retry-After 1–60 s; message quotes your effective limit), or an edge limit (per key, per IP, or platform-wide) (Retry-After: 1; message Too many requests at the edge; retry after 1 second.). On Student and Developer plans, also the plan's organization-wide RPM or too many requests at once, on the free-allowance models only (concurrency_limit_exceeded, allowance_capacity_busy). Also inflight_busy (Retry-After: 10), on /v1/chat/completions: your organization's own requests still running hold the credit this one needs, and it comes back as they finish (a streaming request first waits up to about 25 seconds for them, a non-streaming one up to about 10). Same JSON shape — honour the Retry-After header either way.
Yes, after the window.
499
(informational)
Client closed the connection mid-stream. Billed for tokens produced up to the disconnect.
n/a
500
internal_error
Unhandled server-side fault.
Yes, with backoff.
503
service_unavailable
The model is temporarily unavailable — or, with code large_request_backpressure, a burst of very large requests briefly exceeded the platform's in-flight body budget (Retry-After: 2), or, with allowance_capacity_unavailable, a free-allowance model isn't available on our own GPUs right now, or, with model_overloaded (error.typeservice_unavailable_error), a model on our own GPUs is at capacity and your request could not start within the waiting limit (Retry-After 10–30 s), or, with spend_cap_unavailable, the monthly spend cap on your API key or project could not be checked right now, so the request was not run (Retry-After: 5).
Yes, after Retry-After (30–60 s for a model outage).
Model name not in your catalog. Check GET /v1/models.
model_not_supported_on_endpoint
Model exists but doesn't support this endpoint (e.g. embeddings model on /v1/chat/completions).
invalid_role
A message has a role other than system, developer, user, assistant, tool, or function.
missing_content
A message is missing required content.
max_tokens_exceeded
max_tokens exceeds the model's context window.
empty_input
Embeddings request with an empty input.
input_too_large
The embeddings input array has more than 2,048 entries. Split it into smaller batches.
invalid_request
Generic validation error. Check the param field.
provider_user_error
The provider serving the model rejected the request; the message carries its reason (for example, prompt plus max_tokens over the context window). Fix the request; if the message doesn't point at your request, retry later or pick another model.
unsupported_parameter
The provider serving this model has no equivalent for a parameter you sent; param names it. Remove it or pick another model.
provider_prefix_mismatch
You pinned a provider with provider/model, but that provider does not serve the model.
engine_rejected_request
The model engine rejected the request, usually because prompt plus max_tokens exceeds the context window.
model_does_not_support_images
The model does not accept images. Choose a vision-capable model or remove the image parts.
invalid_image_url
An image or video URL is not https or a base64 data URI, is not publicly reachable, has an unsupported media type, or the inline image is over 5 MB.
remote_media_not_supported
This model accepts images only inline, as base64 data URIs.
too_many_image_parts
More than 20 image or video parts in one request.
invalid_tool_choice
tool_choice is not auto, none, required or a well-formed object.
invalid_logprobs
top_logprobs was sent without logprobs: true.
missing_json_schema
response_format.type is json_schema but no schema was given.
auto_routing_disabled
model: "auto" is not enabled. Choose a model explicitly.
prompt_too_long_for_plan
Student and Developer plans: the prompt (on embeddings, the whole input batch, with param: "input") is longer than your plan's free allowance accepts on this model; the message quotes both sizes. Shorten the prompt or send fewer inputs per request, or use a pay-as-you-go model.
n_not_supported_on_plan
Student and Developer plans: the free allowance runs one completion per request (n: 1) on its models. Send separate requests, or use a pay-as-you-go model.
The token doesn't start with sk- and isn't a valid, unexpired dashboard session token, e.g. an unfilled placeholder such as YOUR_API_KEY (message: Invalid or expired token).
Send Authorization: Bearer sk-... with a key from the dashboard.
key_revoked
The key was revoked.
Create a new key.
key_expired
The key passed its expiry date.
Create a new key; an existing key's expiry can't be changed.
invalid_token_type
Wrong token type for this endpoint.
Use the access token from login, or an API key for API calls.
402 means you need to act on billing before more traffic is accepted (unlike 429, which is temporary). Exceptions: daily_allowance_pending clears by itself within a minute, and daily_allowance_exhausted can clear by itself too when your organization turned off paying from its balance after the free allowance and requests still running hold the rest of it (its message says so). Branch on the error code and read the message, not on the status alone.
Code
Where it fires
Resolution
daily_allowance_pending
Student and Developer plans: today's free allowance for this model hasn't been issued yet. It is granted automatically within a minute of the Cairo day, or your plan, starting.
Retry after a minute. Topping up also lets the model run now, charged to your balance at standard rates, unless your organization turned off paying from its balance after the free allowance (Billing → Plans).
daily_allowance_exhausted
Student and Developer plans: today's free allowance for this model is used up, and your balance can't pay for the request, or your organization turned off paying from its balance after the free allowance (Billing → Plans).
The allowance renews at 00:00 Cairo time. To keep going now, top up: the model is then charged to your balance at standard rates. If paying from the balance after the free allowance is turned off, topping up doesn't help: an owner can turn it back on under Billing → Plans. With it turned off, this code also answers while requests still running hold what is left of the allowance (retry in a moment) or when the request could cost more than what is left (shorten the prompt): read the message.
quota_exceeded
No spendable credit left for a priced model: your balance, minus credit held by requests still running, is at or below 0 EGP — or below the small overdraft your organization gets once it has made a paid top-up (the amount is shown on your dashboard). When only your organization's own requests still running hold that credit, a chat completion naming its model gets 429 inflight_busy instead (retry it), and a model: "auto" request can get either: the 402 when what the running requests leave is too little for its classification step or for every model in its auto pool, the 429 when the chosen model's gate refuses it; embeddings, images and decision models keep this 402: its message counts the credit held by requests still running (with paying from the balance on, daily_allowance_exhausted says the allowance is used up instead), and a retry once they finish can succeed.
Top up under Dashboard → Billing → Charge Balance or redeem a coupon. Models shown as Free in the Model Library need no credit.
insufficient_balance
Your spendable credit can't cover even the prompt plus a one-token reply (for images, the estimated image cost). A chat request you can only partly afford is not rejected: it is served with max_tokens lowered to what your credit covers (X-Output-Clamped header), so the answer may stop early with finish_reason: "length", streaming requests included. Exception: on a model that reasons out of sight (Claude, OpenAI GPT-5 and o-series, Gemini thinking models, Grok) a streaming request's max_tokens is never lowered below 1,024 output tokens, so you get this error when your credit covers fewer than 1,024 and your own max_tokens is larger. While your organization's other requests still running hold the credit, a chat completion naming its model gets 429 inflight_busy instead (retry it), after waiting for them up to about 10 s on a non-streaming request and up to about 25 s on a streaming one, and a model: "auto" request can get either: the 402 when what the running requests leave is too little for its classification step or for every model in its auto pool, the 429 when the chosen model's gate refuses it; the other routes keep this 402: its message counts the credit held by requests still running (with paying from the balance on, daily_allowance_exhausted says the allowance is used up instead), and a retry once they finish can succeed.
Top up or shorten the prompt; on those reasoning models a max_tokens your credit covers is also served; for images, request fewer or smaller images.
spending_cap_reached
Per-key monthly spend cap hit; it resets at the start of the next month (Cairo time). The cap is a hard limit: you are never billed past it. A request the cap can only partly pay for is not rejected: it is served with max_tokens lowered to what the cap has left (X-Output-Clamped), streaming requests included; a non-streaming request without max_tokens is lowered to at most half of it, so another request can run beside it. When the rest of the cap is held by the key's requests still running, the request first waits for them (up to about 10 seconds, or about 25 on a streaming request) and, on a chat completion naming its model, answers 429 inflight_busy instead if they are still running: retry it (a model: "auto" request can get either, depending on whether its classification step or the chosen model's gate refuses it). There this 402 is for a cap with too little left even with nothing running; the other routes answer it while the key's running requests hold the rest, and the message says so.
A key's cap can't be changed after creation: create a new key with a higher cap (or no cap) and switch to it, or wait for the reset.
project_spend_cap_exceeded
Per-project monthly cap hit. It is a hard limit too, with the same lowered max_tokens, and the same wait and 429 inflight_busy on a chat completion naming its model when requests still running hold the rest of it (model: "auto": either answer, as for the key cap).
Raise the cap under Projects → Limits.
A stream that runs out of spendable credit part-way is not an error: it ends cleanly with finish_reason: "length", a usage block and stop_reason: "balance_exhausted" on its last chunk, then data: [DONE]; see Streaming. A stream that reaches its API key's or project's monthly spend cap part-way ends the same way, with stop_reason: "spend_cap_reached".
Example response:
{ "error": { "type": "insufficient_quota", "message": "Monthly spend cap on this project has been reached. An owner can raise the cap under Project → Limits, or wait for next month's reset.", "code": "project_spend_cap_exceeded", "request_id": "req_86By4H0S9VTH8PneVWokg" }}
The raw JSON body of one request may be at most 32 MiB (33,554,432
bytes) on POST /v1/chat/completions, POST /v1/embeddings,
POST /v1/decisions and POST /v1/systemone, and 10 MiB (10,485,760 bytes) on every other route.
Base64 attachments count at their encoded size (4/3 of the file). Within a
chat request, one message holds at most 2,000,000 characters of text and
5 MB (decoded) of media; over either limit you get 422 invalid_request_body.
A request may carry at most 20 image or video parts; over that you get
400 too_many_image_parts.
Code
Meaning
Fix
request_too_large
The body is over the route's cap. The message quotes the declared size (when the client sent Content-Length) and the limit.
Not retryable. Drop earlier turns or tool outputs, or shrink attachments. Agentic clients should compact the conversation.
{ "error": { "type": "invalid_request_error", "message": "Request body too large: 34,000,000 bytes declared; the limit for POST /v1/chat/completions is 33,554,432 bytes (32 MiB). Send fewer or shorter messages and tool outputs, or shrink base64 attachments.", "code": "request_too_large", "request_id": "req_86By4H0S9VTH8PneVWokg" }}
Per-key RPM ceiling exceeded; on Student and Developer plans, also the plan's organization-wide RPM on its free-allowance models, which all its keys share (the message says across your organisation; other models are not affected).
Honour Retry-After. Past the plan's RPM you can also use a pay-as-you-go model. See Rate Limits.
concurrency_limit_exceeded
Student and Developer plans: more requests running at once on the free-allowance models than your plan allows; the message quotes the limit.
Retry after Retry-After (2 s), when one of your requests finishes.
allowance_capacity_busy
The free allowance's shared capacity is full right now.
Retry after Retry-After (5 s), or use a pay-as-you-go model.
inflight_busy
On /v1/chat/completions: your organization's spendable credit is held by its own requests still running, and this one would fit once they finish. It counts across the whole organization, whichever key sent the request, and it also replaces a spend-cap 402 that only requests still running would cause. A streaming request (stream: true) first waits up to about 25 s for those requests and gets this only if they are still running; a non-streaming request gets it at once or after waiting up to about 10 s for them.
Retry after Retry-After (10 s); the credit comes back as those requests end. Credit that is missing even with nothing running gets a 402 instead. So does a request to another route while running requests hold the credit: its message counts the credit held by requests still running (with paying from the balance on, daily_allowance_exhausted says the allowance is used up instead), and a retry once they finish can succeed. A model: "auto" request can get either: the 402 when what the running requests leave is too little for its classification step or for every model in its auto pool, the 429 when the chosen model's gate refuses it.
Retry with backoff; send X-Request-Id to support if persistent.
provider_backings_unavailable
Every provider serving the model failed for this request.
Retry with backoff, or switch to another model from the model library.
no_callable_backing
No provider is currently enabled for this model.
Retry later, or pick another model.
empty_completion
The model returned an empty response.
Retry.
large_request_backpressure
A burst of very large request bodies briefly exceeded the platform's in-flight body budget; your request was refused before it was read.
Retry after Retry-After (2 s) — the official SDKs do this automatically.
no_healthy_backends
Model temporarily unavailable.
Retry, or switch to another model from the model library.
engine_unavailable
Model starting up or overloaded.
Retry once.
model_overloaded
The model runs on our own GPUs and is at capacity: your request could not start within the waiting limit. Nothing was generated and you are not charged. Its error.type is service_unavailable_error.
Retry after Retry-After (10–30 s) — the official SDKs do this automatically.
allowance_capacity_unavailable
Student and Developer plans: the model isn't available on our own GPUs right now, and the free allowance only runs there.
Retry shortly, or use a pay-as-you-go model.
spend_cap_unavailable
Your API key or project has a monthly spend cap, and the gateway could not check it right now, so the request was not run: a cap is never passed. Nothing was charged.
These come from the Student card under Dashboard → Billing → Plans
(the dashboard's /v1/auth/student/* endpoints), never from requests made
with an API key. The card shows each message as it is.
Code
Status
Meaning
What to do
student_verification_disabled
503
Student verification isn't available right now.
Try again later.
email_not_verified
403
Your account email isn't verified yet.
Verify it with the link we emailed you, then try again.
student_personal_org_required
403
The Student plan is for personal accounts, and this account has no personal organization.
Contact support.
student_verification_revoked
403
Student verification is turned off for this account.
Contact support if you think this is a mistake.
org_suspended
403
The account is suspended.
Contact support.
student_not_eligible
403
This account isn't eligible for the Student plan.
Contact support if you think this is a mistake.
student_phone_required
403
The account has no verified mobile number.
Verify your number (the Student card offers it), then try again.
student_phone_not_owned
403
The mobile number on your account is verified on another account.
Verify a number of your own.
invalid_student_email
400
The address isn't a valid email address.
Enter your full university address, like name@university.edu.eg.
student_domain_not_supported
400
The address isn't from a supported university.
Check the supported universities on the Student card.
student_already_verified
409
Your Student plan is active and can't be renewed yet; the message gives the date renewal opens (while the program's end is announced, only your plan's last day).
Renew from that date.
student_account_email_first_time_only
409
Your account email can start the Student plan only the first time, and this account has verified before.
On the Student card, verify your university email with a code.
student_plan_unavailable
409
The Student plan isn't open for new sign-ups right now.
Try again later.
plan_signups_paused
409
New student sign-ups are paused. Students already on the plan can still renew.
Try again later.
plan_program_ending
409
The Student plan has an announced last day, so it takes no new sign-ups or renewals.
A running plan stays active until the last day in the message.
plan_program_ended
409
The Student plan has ended.
—
student_email_already_used
409
This university address is already linked to another SovereignEG account. An address works for one account only, ever.
Sign in to the account that verified it. Support can't move an address to another account.
expired_code
400
The code expired, or was already used.
Request a new code.
invalid_code
400
The code is wrong.
Check the latest email and try again.
too_many_attempts
400
Too many wrong codes.
Request a new code.
rate_limit_exceeded
429
Codes were requested too often: from your account (per hour or per day), for that address, or from your network.
Wait for the Retry-After time.
student_verification_budget_exhausted
503
Today's limit of verification emails is reached.
Try again tomorrow.
student_verification_unavailable
503
Verification is temporarily unavailable.
Try again in a few minutes.
student_email_delivery_failed
503
We couldn't send the code.
Try again in a few minutes.
plan_term_conflict
409
Two verifications ran at the same time.
Reload the Plans page: your plan may already be active.