EZAT RouterDocs

Troubleshooting

Common EZAT Router problems by symptom (wrong base URL, 401, 402, unknown model, 429 and 529, a tool ignoring your settings, cut-off streams) with the cause and the fix.

When to use this page

Use this page when a request or a tool fails. Find the status code or symptom below; each entry gives the cause and the fix. Errors lists every error type in full.

Two quick checks narrow most problems down:

  • Did the request reach EZAT Router? Every Messages or Chat Completions request made with a valid key appears on the dashboard's Usage page within a few seconds, including refused ones (status Rejected). If nothing appears, the tool is sending the request somewhere else, or without a valid key.
  • Which format is the error in? An API error has an error type, such as {"type":"error","error":{"type":"not_found_error",…}} or {"error":{"code":"model_not_found",…}}. A body like {"statusCode":404,"message":"…"} means the URL path itself is wrong.

Base URL

404 with Cannot POST /v1/v1/messages

Cause. The base URL ends in /v1. The Anthropic SDKs and Claude Code add /v1/messages themselves, so the path doubles.

Fix. Use https://api.router.ezat.io with nothing after it: ANTHROPIC_BASE_URL=https://api.router.ezat.io, base_url="https://api.router.ezat.io".

404 from an OpenAI client or tool

The body is {"statusCode":404,…} with a message such as Cannot POST /v1/chat/completions or Cannot POST /openai/chat/completions, or just Not Found.

Cause. The OpenAI base URL is missing /openai/v1, or has only part of it. OpenAI clients add /chat/completions and /models to the base URL.

Fix. Use https://api.router.ezat.io/openai/v1 exactly, for example OpenAI(base_url="https://api.router.ezat.io/openai/v1") or OPENAI_BASE_URL=https://api.router.ezat.io/openai/v1. See OpenAI-compatible base URL.

Authentication

401 Missing API key

The message is Missing API key. Send it in the x-api-key or Authorization: Bearer header.

Cause. No key arrived. The header is missing or misspelled, or the environment variable that should hold the key is empty in the process that sent the request. Apps started from the Dock, the Start menu or an IDE don't see variables exported in a terminal.

Fix. Send the key as x-api-key or Authorization: Bearer. Check that the variable is set in the same shell or app that runs the tool, without printing the key:

printf 'length %s, prefix %s\n' "${#EZAT_API_KEY}" "${EZAT_API_KEY:0:8}"

It should print length 48, prefix ezat_sk_.

401 Invalid API key

Cause. The value that arrived isn't a working EZAT Router key:

  • a typo, a copy that was cut off, or quotes, spaces or a line break inside the key (spaces at the ends are ignored);
  • a key from another provider, such as an Anthropic or OpenAI key;
  • two keys at once. When a request has both x-api-key and Authorization, EZAT Router reads x-api-key. A tool with an old ANTHROPIC_API_KEY still set sends it as x-api-key, and that hides the EZAT Router key in ANTHROPIC_AUTH_TOKEN.

Fix. Check the length and prefix as above. Unset any other provider's key that the tool also reads (unset ANTHROPIC_API_KEY), or set it to your EZAT Router key too. If the key still fails, create a new one on the API keys page.

401 revoked or expired key

The message is This API key has been revoked or This API key has expired.

Cause. Someone revoked the key, or it passed the expiry date chosen when it was created.

Fix. Create a new key on the API keys page and update the tool. A key can't be reactivated.

403 permission error

Cause. One of:

  • This API key is not allowed to use …: the key was created with Only selected models, and this model isn't one of them.
  • This organization is suspended. Contact support@ezat.io.: the organization's keys are all refused.

Fix. For the first, use a model the key allows (GET /v1/models with the key lists them) or create a key for all models. For the second, email support@ezat.io.

Balance and limits

402 credit balance too low

The message is Your credit balance is too low. Add credits in the EZAT Router dashboard. In the OpenAI format the error type is insufficient_quota.

Cause. The organization's balance is zero or below. Requests are refused until it is above zero.

Fix. Add credit on the Billing page (owners, admins and billing members can). Credit appears a few seconds after payment. If you added credit and still get 402, check that you added it to the organization the key belongs to: the organization switcher in the top bar shows which one you are looking at. See How billing works.

402 spend limit reached

The message is This API key reached its daily spend limit of … (or monthly, or total).

Cause. The key has a spend limit, and it has spent that much in the current period.

Fix. A daily or monthly limit resets at the start of the next UTC day or month. Otherwise, use a key with a higher limit, or create one. See Spend limits.

429 rate limit

The error type is rate_limit_error, with a retry-after header in seconds. The message tells you which limit:

  • This API key exceeded its requests-per-minute limit (retry-after: 30): the key sent more than its requests per minute.
  • Rate limited upstream. Please retry shortly. (retry-after: 10): the model's capacity is rate limited right now.

Fix. Wait the number of seconds in retry-after, then retry with backoff. The Anthropic and OpenAI SDKs retry these on their own. If your own traffic hits the per-key limit, spread it over time. See Rate limits.

529 overloaded (503 in the OpenAI format)

The error type is overloaded_error (server_error with code overloaded in the OpenAI format), with a retry-after header. The message may say the model has no available capacity right now.

Cause. No capacity for this model is free right now. EZAT Router has already tried the other capacity it has for the model before returning this error.

Fix. Retry after the retry-after seconds, with backoff. If it keeps happening, try another model.

Models and requests

404 unknown model

In the Anthropic format: not_found_error with the message model: <the name you sent>. In the OpenAI format: code model_not_found.

Cause. The name isn't a model id or alias that EZAT Router serves to this key. Common reasons: a typo; a name from another provider or a cloud provider's own id; a model that has been retired; a model in preview, which only keys with preview access can call.

Fix. List the models your key can use with GET https://api.router.ezat.io/v1/models and send one of those ids. The Models page lists the other names each model accepts. Names are not case-sensitive. In Claude Code, if a model you picked isn't served, set ANTHROPIC_MODEL to an id from the list.

400 from the model

The error type is invalid_request_error, and the message names a field or a value.

Cause. The request has something the model doesn't accept. EZAT Router checks only model, max_tokens and messages, and passes everything else to the model as you sent it, so the model's own checks apply: for example a sampling parameter (temperature, top_p, top_k) that the model doesn't take, or an anthropic-beta feature it doesn't serve. Message Batches, the Files API, Anthropic-run server tools (web search, code execution) and the MCP connector aren't available.

Fix. Remove the field the message names. If Claude Code gets 400 errors naming unknown fields or beta features, set CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1 in its environment. On the OpenAI-compatible API, a few OpenAI fields are refused on purpose (for example n above 1, logprobs, logit_bias, audio and the legacy functions): see Chat Completions.

413 request too large

The error type is request_too_large.

Cause. The request body is larger than 32 MB.

Fix. Send smaller images or documents, or fewer of them per request.

Tools and settings

A tool still uses its own key or base URL

Symptoms: requests don't appear on the Usage page, the tool reports another provider's errors, or you get 401 although the key is right.

Cause. The tool reads its settings from somewhere that wins over the value you set:

  • Claude Code uses the env block of its settings files over variables exported in your shell. A saved claude.ai login, or an ANTHROPIC_API_KEY you haven't approved, can also be in play.
  • SDK code that passes a base URL or key in the constructor ignores the environment variables (ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY, OPENAI_BASE_URL, OPENAI_API_KEY).
  • Apps started outside your terminal (editors, desktop apps) don't see your shell exports.
  • Two keys at once: see 401 Invalid API key.

Fix.

  • In Claude Code, run /status. The Anthropic base URL line should show https://api.router.ezat.io, and an Auth token or API key line should name the variable that holds your EZAT Router key. If the base URL line is missing, the variable didn't reach Claude Code. Check ~/.claude/settings.json, the project's .claude/settings.json and .claude/settings.local.json for env values that override yours. If Claude Code warns about two credentials, run /logout to drop the saved login. See Claude Code.
  • In your code, pass base_url and the key explicitly, or remove the explicit values so the environment variables apply.
  • For editors and desktop apps, set the values in the app's own settings.

Streaming stops early

Cause. One of:

  • The model failed mid-stream. Once output has started, EZAT Router can't switch to other capacity, so the stream ends with an error event: event: error in the Anthropic format, or a data: chunk with an error object in the OpenAI format. A request that fails like this isn't charged.
  • Your client or a proxy closed the connection. EZAT Router stops the model. You are charged for the input and for the output generated so far, which is estimated when the stream ended before the final count: the Usage page marks such requests as estimated, with the status Cancelled.
  • A read timeout in your client is shorter than the gap between events. EZAT Router sends a keep-alive (an event: ping in the Anthropic format, an SSE comment in the OpenAI format) after 15 seconds without output.

Fix. Retry a request that ended with an error event. Make sure your client's read timeout is well above 15 seconds and that no proxy buffers or cuts long responses.

504 on a long request

The error type is timeout_error, with the message The model took longer than 590 seconds. Send long requests with "stream": true.

Cause. A request without streaming gets no response until the model finishes, and EZAT Router ends it after 590 seconds.

Fix. Send long requests with "stream": true (or the SDK's streaming call).

Contacting support

If you can't fix a problem, email support@ezat.io with:

  • the request-id header of the response, or the x-request-id header if there is no request-id (Anthropic-format error bodies carry the same value as request_id);
  • the time of the request (with time zone), the endpoint, the status code and the error message;
  • your Organization ID from Settings, for billing questions.

Never send your API key: support never needs it.

For AI agents

  1. Read the status code and the error type before changing anything. Don't retry 400, 401, 402, 403, 404 or 413.
  2. For 429, 500 and 529 (503 in the OpenAI format), wait at least the retry-after seconds and retry with backoff.
  3. A 404 with a statusCode field means the URL path is wrong: use https://api.router.ezat.io for Anthropic-format clients and https://api.router.ezat.io/openai/v1 for OpenAI-format clients.
  4. To check the key, print only its length and first 8 characters, then call GET https://api.router.ezat.io/v1/models.
  5. When asking the user for help, give them the request-id (or x-request-id) and the error message, never the key.

On this page