Troubleshooting

Error reference: Claude Code and Codex on a third-party API

The same error line often has completely different causes when you go direct versus through a gateway. This reference is organised in five layers — network, auth, protocol, model, context — with a copy-paste probe and a decision rule for each.

Verified 2026-10-26Applies to
Claude Code 2.xCodex CLI 0.154.0

How to use this page

Do not start by searching the error text. Start by working out which layer failed. Almost every AI-client error comes from one of five:

  1. Network: the request never left your machine
  2. Auth: it arrived, but the key was rejected
  3. Protocol: the key was fine, the path or format was not
  4. Model: the protocol worked, the model does not exist
  5. Context: the model is running, the input is too long

Layering matters because each layer has a completely different fix, and the error text rarely tells you which one you are in.

Diagnose by HTTP status

These commands check the model list and three protocols, showing the HTTP status of each request:

Set your own KimiSeek API key in the same terminal that will run curl, replacing the placeholder. A credential configured in your client does not automatically populate this shell variable:

Shell · API key
# Replace the placeholder with your own key from the dashboard.
export KIMISEEK_API_KEY="ks-your-key"
Shell · API diagnostics
# Inspect each HTTP status and error body; a model list does not prove sufficient balance.
# 1. Is the key valid at all? (lists models)
curl -sS --max-time 30 -w '\nHTTP %{http_code} /v1/models\n' https://api.kimiseek.app/v1/models \
  -H "Authorization: Bearer ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}"

# 2. OpenAI Chat Completions
curl -sS --max-time 30 -w '\nHTTP %{http_code} /v1/chat/completions\n' https://api.kimiseek.app/v1/chat/completions \
  -H "Authorization: Bearer ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}" \
  -H "Content-Type: application/json" \
  -d '{"model":"deepseek-v4-pro-0813","messages":[{"role":"user","content":"ping"}],"max_tokens":8}'

# 3. Anthropic Messages (the protocol Claude Code speaks)
curl -sS --max-time 30 -w '\nHTTP %{http_code} /v1/messages\n' https://api.kimiseek.app/v1/messages \
  -H "x-api-key: ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}" \
  -H "anthropic-version: 2023-06-01" \
  -H "Content-Type: application/json" \
  -d '{"model":"deepseek-v4-pro-0813","max_tokens":8,"messages":[{"role":"user","content":"ping"}]}'

# 4. OpenAI Responses (the protocol Codex speaks)
curl -sS --max-time 30 -w '\nHTTP %{http_code} /v1/responses\n' https://api.kimiseek.app/v1/responses \
  -H "Authorization: Bearer ${KIMISEEK_API_KEY:?Set KIMISEEK_API_KEY before running this command}" \
  -H "Content-Type: application/json" \
  -d '{"model":"deepseek-v4-pro-0813","input":"ping","max_output_tokens":16}'

Read the HTTP status after each response and its error.code, error.type, and message. The failed step alone cannot establish protocol support. A 200 model list validates the key, not the balance: a zero-balance account can receive 200 at step 1 and 402 at step 2.

Status or errorInterpretationNext action
200 with the expected response structureThis endpoint request worked; not all tool capabilities are verifiedTest client configuration and real tool calls next
401 / 403Credentials, key limits, or model access permissionsCheck key validity, enabled status, expiry, limits, and upstream authorization
402 / insufficient_balanceInsufficient account balanceAdd funds and retry; protocol settings need no change
400 / 404 with model_not_found, not_found_error, or a missing-model messageIncorrect or disabled model ID, or missing upstream model accessSelect the full ID from the model list and verify channel access
400 with an invalid-parameter messageIncompatible request fields or model limitsCheck messages, tools, and token limits against the error body
404 explicitly naming a missing route or endpointIncorrect path or an endpoint the gateway does not provideCheck Base URL and /v1, then verify protocol support; 404 alone does not distinguish a missing model from a missing route
429Rate limit, quota, or upstream overloadInspect the error, wait before retrying, or adjust usage
5xxTemporary gateway or upstream failureKeep the error and request ID, then retry later
HTTP 000 / curl connection or timeout errorNo HTTP response; each probe waits at most 30 secondsCheck DNS, proxies, and the network; a probe timeout does not prove a missing protocol

Claude Code side

No credentials

Claude Code · no credentials
Invalid API key · Please run /login

This means Claude Code found no credentials at all. Check whether ANTHROPIC_AUTH_TOKEN is set in the shell that launched it — a classic mistake is exporting in one terminal and starting the client in another.

401 unauthorised

Claude Code · 401
API Error: 401 {"type":"error","error":{"type":"authentication_error","message":"invalid api key"}}

Causes, in order of likelihood:

  1. The key was copied with a trailing space or newline
  2. The key was revoked or its quota is exhausted
  3. ANTHROPIC_API_KEY is set but empty, so the client falls back to a login session

403 forbidden

Claude Code · 403
API Error: 403 {"type":"error","error":{"type":"forbidden","message":"invalid x-api-key"}}

Going direct, this usually means the key is invalid. Through a gateway, the more common cause is a header mismatch: some gateways only accept Authorization: Bearer, others only x-api-key. KimiSeek accepts both, but if you have another proxy in between, the header may be rewritten.

model not found

Claude Code · model not found
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"model: deepseek-v4-flash-0731 not found"}}

Two possibilities: a misspelled model name, or a retired model. A retired model id keeps returning not found instead of saying it was retired, which is the most time-consuming trap here — you end up auditing configuration when the real answer is that the model was replaced.

Replace it with a real id from the models page.

The stream cuts out

Claude Code · stream cut
API Error: stream disconnected before completion: stream closed before completion

A streaming connection was cut mid-flight. Check in this order:

  1. Whether a local HTTP proxy (HTTPS_PROXY) is intercepting
  2. Whether the corporate network times out long responses
  3. Whether a per-request server limit fired

The upstream request timeout is 600 seconds for /v1/messages (Claude Code) and 175 seconds for /v1/responses (Codex). Clients or intermediate proxies may disconnect earlier; diagnose the failure using the actual endpoint and error details.

Context overflow

Claude Code · context overflow
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"prompt is too long: 210000 tokens > 200000 maximum"}}

Note that the 200000 here is the client's or the model's limit, not necessarily what you expected. On DeepSeek V4 Pro the real limit is 1M, so seeing 200000 means the request did not reach the model you think it did, or the client truncated at Claude's spec.

Codex side

401 Missing bearer

Codex · 401
■ unexpected status 401 Unauthorized: Missing bearer

env_key in config.toml is only a variable name; the value has to be in the environment. This error is "you named the variable, but it is empty".

404 Not Found

Codex · 404
■ unexpected status 404 Not Found

Eight times out of ten the base_url is missing /v1. Codex builds base_url + "/responses", so without /v1 it hits a web page.

After checking base_url, inspect the response body for a missing model as well. If the gateway truly lacks /v1/responses, use a Responses-compatible gateway or translation layer; current Codex rejects wire_api = "chat". See the Codex guide.

Stream interruption

Codex · stream cut
■ stream disconnected before completion

Same streaming problem as Claude Code, but Codex is more sensitive to it because its execution loop depends on a complete event stream. On an unstable network, change networks rather than retrying.

Two typical network failures

Shell · network layer
fetch failed
ECONNREFUSED 127.0.0.1:7890

fetch failed is Node's generic network error and carries no information by itself. The useful line is ECONNREFUSED 127.0.0.1:7890 — a local port like that means a local proxy took over the request and the proxy is not running or its rules are wrong.

This is the failure most often misdiagnosed as "the gateway is down". The test: if curl works and the client does not, the client's shell environment differs from curl's.

Same error, different cause

This is the mental model that matters most with a gateway:

ErrorGoing directThrough a gateway
invalid x-api-keyThe key is invalidThe header name is unrecognised, or an intermediate proxy rewrote it
model not foundWrong model nameThe gateway's model map lacks this id, or it is retired
stream disconnectedOfficial service hiccupLocal proxy, corporate network, or gateway timeout
prompt is too longOver 200KThe gateway routed to an upstream with a smaller context
401Bad keyKey is fine, the environment variable never reached the client

What to include when you ask for help

Four things, all of them, or nobody can diagnose it:

  1. The full error line, not a cropped screenshot
  2. The result of the layered curl probe — which of the four steps failed
  3. Client versions (claude --version, codex --version)
  4. The model id and Base URL in use, with the key redacted

Verification

  • Verified: 2026-10-26
  • Error examples help locate the failing layer; exact wording can vary by client version. Include your installed version when reporting a problem. The Codex configuration was checked with 0.154.0.

FAQ

curl works, the client does not. Why?

Most often the environment variable is not in the same shell. The client reads its own process environment, so exporting in another terminal does nothing. Confirm echo $ANTHROPIC_AUTH_TOKEN has a value in the shell that launched the client.

What is the real difference between 403 and 401?

401 is 'I do not know who you are'; 403 is 'I know who you are and you may not do this'. Through a gateway, 403 is usually a header or routing policy problem, while 401 is usually the key itself or an environment variable.

Context overflow says 200000, but the model claims 1M. Why?

It means the request did not reach the model you think it did. Either the model id fell back to a default, or the client truncated at Claude's spec. Check the id with /v1/models, then check the context window setting in the client.

Will retrying fix a broken stream?

Usually not. A broken stream is a connection-layer problem, and a retry just repeats the same failure. Check the proxy and network first, then split long jobs into smaller ones.