Error Troubleshooting Guide: Quick Reference for 401 / 429 / 500

(Unofficial)

This guide is independently community-maintained. It is not affiliated with, endorsed by, or sponsored by the vendor of the third-party tool it covers. All third-party trademarks are the property of their respective owners.

What do you do when a Claude API call returns 401 Unauthorized, 429 Too Many Requests, or 500 Internal Server Error? This article groups errors by status code, and walks through the cause, the fix, and whether you need to contact support. Updated 2026-05-15: aligned with AI Gateway repositioning (technical "proxy" terms in this article refer to corporate/intermediate HTTP proxies, not positioning).

Error Troubleshooting Guide

TL;DR: Read the status code first — 401 = bad API key, 403 = no balance / suspended, 429 = rate-limited (exponential backoff), 5xx = Anthropic upstream blip (retry), 400 = your request params are wrong (you fix it).

When you hit an error calling the Claude API, look at the status code first — most issues don't need support and you can fix them yourself. This article groups errors by status code, with the cause, the fix, and when to contact support.

401 Unauthorized: authentication failed

Typical response:

json
{
  "error": {
    "type": "authentication_error",
    "message": "invalid x-api-key"
  }
}

Possible causes:

  1. API key typo (a missing character, an extra space, a substituted character)
  2. The API key has been disabled or deleted
  3. Wrong header format — not using x-api-key or Authorization: Bearer
  4. Using an Anthropic-issued key (you should be using the CodeGateway-issued key, which starts with sk-cg-)

How to fix:

  1. Log in to the Dashboard → API Keys page and confirm the key starts with sk-cg-
  2. Check that the key status is "Enabled"
  3. When copying the key, don't include trailing spaces — using the Dashboard "Copy" button is the safest way
  4. Set the key in your .env or environment variables:
bash
export ANTHROPIC_AUTH_TOKEN="sk-cg-YOUR_KEY"
export ANTHROPIC_BASE_URL="https://api.codegateway.dev"

When to contact support: you've worked through every self-service step above and still get 401, even though the Dashboard shows the key is enabled.

403 Forbidden: account disabled / insufficient balance

Typical response:

json
{
  "error": {
    "type": "permission_denied",
    "message": "insufficient balance"
  }
}

Possible causes:

  1. Insufficient balance (most common): the account balance has been spent down
  2. The account is temporarily disabled by risk control (very rare)
  3. The model isn't covered by your plan (no such restriction today, kept for future use)

How to fix:

  1. Dashboard → Overview shows the live balance
  2. If your balance is near zero or zero → top up from the Billing page
  3. If your balance is healthy but you still get 403 → contact support

When to contact support: balance is ≥ $1 but you still get 403.

429 Too Many Requests: rate limit hit

Typical response:

json
{
  "error": {
    "type": "rate_limit_error",
    "message": "rate limit exceeded for your plan"
  }
}

Possible causes:

CodeGateway currently rate-limits all users at a single 60 RPM ceiling. A 429 typically means a burst of requests in a short window.

Current rate-limit policy: all users share a single 60 RPM ceiling (60 requests per minute). The TPM (Tokens Per Minute) field is reserved in config but not currently enforced.

CodeGateway has not yet shipped paid plan tiers (Starter / Pro / Team, etc). When we do, we'll announce it and update this doc.

Not every 429 is your quota. Upstream wholesale rate limiting — the model provider temporarily capping us — is not caused by your traffic, and retrying is the right response. Distinguish it by the error type, not the status code: your own quota returns "type": "rate_limit_error", while the upstream case returns "type": "upstream_rate_limited" (usually alongside a Retry-After header). On /v1/responses only, that upstream case is delivered as 503 instead of 429 — see the 5xx section below.

How to fix:

  1. Exponential backoff retry: wait 1s after the first failure, 2s after the second, 4s after the third — up to 3 attempts. This is Anthropic's officially recommended strategy.
  2. Batching: for offline workloads (bulk log analysis, bulk test-case generation, etc.), insert await sleep(N) to throttle and spread RPM evenly
  3. Upgrade your plan: if your peak usage stays close to the limit long-term, upgrade to a higher-RPM plan from the Dashboard

Code example (Node.js exponential backoff):

bash
async function withRetry<T>(fn: () => Promise<T>, maxAttempts = 3): Promise<T> {
  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    try {
      return await fn()
    } catch (e: any) {
      if (e.status !== 429 || attempt === maxAttempts) throw e
      const delay = 1000 * 2 ** (attempt - 1) // 1s, 2s, 4s
      await new Promise(r => setTimeout(r, delay))
    }
  }
  throw new Error('unreachable')
}

When to contact support: your peak workload exceeds even the Team plan's RPM/TPM — we can configure a custom limit for enterprise users.

500 / 502 / 503: upstream errors

Typical response:

json
{
  "error": {
    "type": "api_error",
    "message": "upstream error"
  }
}

Possible causes:

  1. 502/503: Anthropic upstream is briefly unavailable (most common, usually recovers within a few minutes)
  2. 500: the CodeGateway gateway itself is having a problem (very rare — monitoring alerts immediately)

"type": "upstream_rate_limited" on /v1/responses: the provider's wholesale channel is temporarily rate limiting us. This is delivered as 503 with a Retry-After header — honor that header and retry the same request; it is not a problem with your request. The other endpoints report the same upstream event as 429 (see the 429 section above).

How to fix:

  1. Just retry: 5xx is transient — a dumb exponential backoff retry usually succeeds
  2. Don't change the request: 5xx isn't a problem with your request, retrying the exact same request is what you want
  3. Still 5xx after 5 minutes → check Anthropic Status
  4. Anthropic Status looks healthy but CodeGateway still 5xx → contact support (very rare)

When to contact support: 10+ minutes of continuous 5xx, with Anthropic Status reporting all clear.

400 Bad Request: invalid request parameters

Typical response:

json
{
  "error": {
    "type": "invalid_request_error",
    "message": "messages: missing required field"
  }
}

Possible causes:

  1. Missing required fields (such as model, messages, max_tokens)
  2. Field with the wrong type (e.g. messages isn't an array)
  3. Misspelled model name (e.g. writing claude-sonnet-4 instead of claude-sonnet-4-6)
  4. max_tokens exceeds the model's ceiling
  5. Wrong message role order (must alternate user → assistant — you can't have two consecutive user messages)

How to fix:

  1. Read the message field carefully — Anthropic's error messages are specific and usually point to the exact problem field
  2. Cross-check the request format against the Anthropic official docs
  3. Use curl to send a minimal request standalone and confirm the basic parameters

Minimal working request example:

json
curl https://api.codegateway.dev/v1/messages \
  -H "x-api-key: $ANTHROPIC_AUTH_TOKEN" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Hi"}]
  }'

Cross-model thinking / reasoning fields (a top source of first-call 400s)

If you switch models and keep the previous model's thinking / reasoning params, the upstream returns 400 invalid_request. Three common cases:

  • thinking.* (Claude extended thinking):

  • thinking.type=disabled is rejected on claude-*-5-5 (always-on adaptive thinking) — the model cannot turn thinking off, so you get 400. Use thinking.type=between_tools or thinking.type=adaptive + output_config.effort instead.

  • thinking.type=enabled also 400s on models without classic extended thinking.

  • reasoning_effort / context_management: OpenAI / Responses-style params. On the Anthropic Messages path (or any model that does not know them) the upstream replies Extra inputs are not allowed. Drop them when switching models, or map to the target model's documented equivalent.

Live error (2026-10-13):

json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "thinking.type.disabled is not supported on claude-sonnet-5-5. Use thinking.type.between_tools (lowest) or thinking.type.adaptive + output_config.effort. The model cannot disable thinking."
  }
}

If the response carries an x-codegateway-translation-warnings header, the gateway stripped decorative extras — it never silently turns off real thinking intent (that still fails closed with 400).

anthropic-version must be a single version

  • Do not comma-join multiple values: "2023-06-01, 2023-01-01" returns 400.

  • Correct: anthropic-version: 2023-06-01

Live error (2026-10-13; same shape as first-call 400 samples):

json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "anthropic-version: \"2023-06-01, 2023-01-01\" is not a valid version"
  }
}

role: system differs across the two endpoints

  • Anthropic Messages (POST /v1/messages): put the system prompt in the top-level system parameter — do not send {"role":"system"} inside messages.

  • OpenAI Chat Completions (POST /v1/chat/completions): {"role":"system"} is valid — put it first in the messages array.

Live Messages-path error (2026-10-13):

json
{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "messages.0: use the top-level 'system' parameter for the initial system prompt; the directive-only form (content: [] with output_config) is accepted at any position"
  }
}

When to contact support: usually never — 400 means the parameters are wrong, you fix them yourself.

context window exceeded: prompt is too long

Typical response:

bash
prompt is too long: <X> tokens > <max> tokens

Possible causes:

Input + expected output token count exceeds the model's context window (Sonnet 4.6 = 1M tokens, Opus 4.6-4.8 = 1M, Opus 4.5 = 200K, Haiku = 200K).

How to fix:

  1. Use the Anthropic tokenizer to estimate token count locally
  2. Truncate history: keep only the last N turns of the conversation
  3. Replace with a summary: summarize long documents with Haiku first, then pass the summary to Sonnet/Opus
  4. Chunk it: split a long document into chunks, process each independently, then merge the results

Network errors: connection reset / timeout

If the error doesn't carry an HTTP status code (such as ECONNRESET or ETIMEDOUT), it's at the network layer:

  1. Check your local network (can you ping api.codegateway.dev?)
  2. Check your proxy settings (especially on a corporate network)
  3. SSE streaming requests need a long-lived connection — make sure no intermediate proxy enforces a 60s timeout

Still stuck?

Open the Dashboard → bottom-right feedback widget, and include:

  • The error code + the raw error response (json)
  • An example request (with the API key removed)
  • When it happened (down to the minute)

We'll get back to you with a diagnosis within 24 hours.

FAQ

Q: 401 but the API key looks right — what do I check first?

A: In this order — 1) check the dashboard, confirm the key is enabled; 2) verify there’s no extra whitespace or missing character (use the “copy” button, don’t retype); 3) confirm the header is x-api-key or Authorization: Bearer (not ANTHROPIC_AUTH_TOKEN); 4) if every self-service step passes and you still get 401, contact support.

Q: Persistent 5xx — is it CodeGateway’s problem or Anthropic’s?

A: Check Anthropic Status first (status.anthropic.com). If Anthropic is reporting an incident, wait it out (CodeGateway transparently passes upstream errors through). If Anthropic is fully green and you've been getting 5xx for 10+ minutes, that's CodeGateway-side — ping support immediately.

Q: My streaming (SSE) requests sometimes drop mid-flight. What's going on?

A: Almost always a corporate proxy / firewall killing long-lived connections. Allow-list *.codegateway.dev and disable the intermediate proxy's connection timeout. CodeGateway sends a 15-second keep-alive heartbeat at the Cloudflare edge; if some middlebox strips that heartbeat, the long stream eventually drops.

  • API Usage Tutorial — basic call examples
  • Tiered Markups Explained — billing mechanics
  • API Key Security Best Practices — key management

References

Turn this doc into a real API call

Lacking an official key or facing overseas card payment issues? Create an sk-cg- key after signing up, point your base URL at CodeGateway, and keep your existing SDK or CLI unchanged. Pay per token; binding a card adds free credit.

Sign up free
Author:CodeGateway teamReviewed on:2026-05-16