When Kimi API returns an error, look at three things first: the HTTP status code, the error.type, and the request_id. A 429 may mean server overload, organization-level rate limiting, or an insufficient balance; a 401 may mean a mistyped key or a mix-up between the China and international sites. Classify the error before changing code.

This article breaks the problem into four categories — 401, 404, 429, and timeouts — and gives causes, troubleshooting steps, and reusable backoff code. Models and prices follow the model pricing page.

Note: Moonshot and Kimi are trademarks of their respective owners. Error types, rate-limit rules, and API behavior may change. This article reflects common conditions as of October 2026 and defers to the official documentation.

1. Status Code Quick Reference

Status Error type Common meaning What to do
400 invalid_request_error Bad parameters, context too long, output limit out of range Fix the request
400 content_filter Input or output triggered content safety Adjust the prompt
401 invalid_authentication_error Invalid key, region mismatch Fix credentials
401 incorrect_api_key_error Key missing or incorrect Fix credentials
403 permission_denied_error Endpoint not enabled, IP allowlist, balance or permission issue Check permissions and balance
404 resource_not_found_error Wrong model name or path Check the model list
429 engine_overloaded_error Server overloaded Back off and retry
429 rate_limit_reached_error Concurrency, RPM, TPM, or TPD limit exceeded Slow down or request a higher quota
429 exceeded_current_quota_error Arrears, insufficient balance, expired voucher Top up
499 client_closed_request Client or proxy closed the connection early Check timeouts and streaming
500 server_error Internal server error Back off and retry
503 server_unavailable Service temporarily unavailable Back off and retry
504 Gateway Time-out Long request waited too long Switch to streaming

An insufficient balance may appear as 403 or 429 depending on the entry point, so do not rely on the status code alone; check error.type. Log at least the timestamp, status code, error type, model name, and request_id, and never log full keys or sensitive content.

2. 401: Check the Region, Then the Key

  1. Is a China-site key paired with the international endpoint, or vice versa? The two sites' accounts, balances, and keys are completely independent.
  2. Are you mixing keys from different product lines, such as the open platform, Kimi Code, and membership products?
  3. Does the key contain leading or trailing spaces, newlines, or extra quotes?
  4. Is the environment variable actually loaded? Print only the prefix to confirm.
  5. Has the key been deleted or rotated, or does it lack permission for the current project?
  6. Is the header Authorization: Bearer <key>, and is the path /v1/chat/completions?
export MOONSHOT_API_KEY="your-key"

curl "https://api.moonshot.cn/v1/chat/completions" \
  -H "Authorization: Bearer $MOONSHOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "kimi-k2.6",
    "max_completion_tokens": 64,
    "messages": [{"role": "user", "content": "Reply with OK only"}]
  }'

If this command returns 200, the key, region, and model name are all correct. If it still returns 401, test with a known-good key to separate a key problem from a gateway configuration problem.

3. 404: Model Name and base_url Are the Usual Suspects

A 404 does not necessarily mean the model has been retired. There are four common causes:

  • When using the OpenAI SDK without setting base_url, the request goes to the default OpenAI endpoint and returns a model-not-found error.
  • The model name is misspelled, or the account does not currently have access to that model.
  • The path has an extra or missing /v1, or the chat endpoint was written as some other path.
  • Model names and permissions differ between the China and international sites.

First, pull the model list with the same key to see what the account can access:

curl "https://api.moonshot.cn/v1/models" \
  -H "Authorization: Bearer $MOONSHOT_API_KEY"

Do not guess at models that are absent from the list. Availability is determined by what the account actually returns and by the model pricing page. If the model list works but the chat endpoint still returns 404, check whether the path is missing /v1, and whether the client has concatenated base_url and the full path twice.

4. 429: Three Types, Three Different Responses

error.type Meaning Retryable? Handling
engine_overloaded_error Server overloaded Yes Back off according to Retry-After, reduce concurrency
rate_limit_reached_error Organization-level concurrency, RPM, TPM, or TPD limit exceeded Partially Slow down, split keys, request a higher tier
exceeded_current_quota_error Arrears, insufficient balance, expired voucher No Top up or check the bill

TPD limit exhaustion usually means waiting until the next day or raising the quota; retrying is pointless. Requests interrupted by a 429 are normally not billed, but a successful retry is billed as usual. Do not retry endlessly out of fear of spending, and do not assume a 429 means the account has already been charged. The OpenAI SDK retries automatically by default, which can turn one 429 into several requests; in production, set max_retries explicitly and use your own backoff logic.

import random
import time
from openai import OpenAI, RateLimitError

client = OpenAI(
    api_key="your-key",
    base_url="https://api.moonshot.cn/v1",
    max_retries=0,
)

def ask(prompt: str, retries: int = 4) -> str:
    for attempt in range(retries):
        try:
            resp = client.chat.completions.create(
                model="kimi-k2.6",
                messages=[{"role": "user", "content": prompt}],
                max_completion_tokens=1024,
            )
            return resp.choices[0].message.content
        except RateLimitError as exc:
            body = exc.body or {}
            etype = (body.get("error") or {}).get("type", "")
            if etype == "exceeded_current_quota_error":
                raise RuntimeError("Insufficient balance or quota; top up first")
            wait = min(2 ** attempt, 20) + random.random()
            print(etype, "waiting", round(wait, 1), "seconds")
            time.sleep(wait)
    raise RuntimeError("Retry limit exhausted")

Retries are only appropriate for transient errors. For operations that have already produced side effects, use an idempotency key or a status check to confirm whether the operation ran before deciding to resend.

5. Timeouts and 504s

Long-form generation, long-document analysis, and code agents are the most likely to hit timeouts. Handle them in this order:

  1. Change non-streaming calls to stream=True so the connection keeps returning data.
  2. Set sensible connection and read timeouts instead of keeping the SDK defaults.
  3. Check whether corporate proxies, gateways, or local routing tools are closing connections early; this may appear as a 499.
  4. Use max_completion_tokens to cap single-response length, and split very long tasks into stages.
  5. Record the request ID and elapsed time for every timeout to distinguish a slow model from a slow network or a slow gateway.
stream = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[{"role": "user", "content": "Write a deployment checklist"}],
    max_completion_tokens=2048,
    stream=True,
    stream_options={"include_usage": True},
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="")

Streaming does not lower the unit price, but it significantly reduces the waste of "wait until timeout, then retry." Connection timeouts can be set short, while read timeouts should accommodate the longest generation time; in streaming scenarios, do not reuse a non-streaming read timeout, or the client will cut the connection while generation is proceeding normally.

6. A Troubleshooting Order

  1. Record the status code, error.type, request_id, model name, and timestamp.
  2. For 401 and 403, check region, key, product line, permissions, and balance.
  3. For 404, check base_url, model name, and account permissions, and verify against the model list.
  4. For 400, check context length, output limits, file format, and content safety.
  5. For 429, use error.type to separate overload, rate limiting, and non-payment.
  6. For 499 and 504, check streaming, timeouts, proxies, and connection keep-alive.
  7. For 500 and 503, back off and retry; if they persist, contact the provider with the request_id.
  8. After every incident, add monitoring and alerts instead of waiting for users to report the problem.

FAQ

What is the difference between 429 and 503?

A 429 may be server overload, an account quota issue, or a balance problem, so check error.type first; a 503 means the service is temporarily unavailable and usually resolves after backoff and retry. What they have in common is that you should not hammer either one at a fixed interval.

Still getting 401 after topping up?

First confirm that the top-up and the key belong to the same region and the same product line. Test with a newly created key to rule out a deleted old key or a cached environment variable.

What error does an overlong context produce?

Usually a 400 invalid_request_error, with a message mentioning that the input tokens are too long. Shorten the input, trim history, or switch to a model with a larger context.

Should SDK auto-retry be enabled?

It can be enabled, but set a limit. Default retries may amplify a 429; in production it is better to disable SDK auto-retry and implement exponential backoff and alerting by error type yourself.

How do I tell a gateway error from an upstream error?

Send the same request to both the direct endpoint and the gateway, and compare the status code, error.type, and request_id. That quickly identifies whether the problem is upstream, the network, the key, or gateway configuration.

Next Steps

Start by creating a test key on the ZSQH AI Gateway, rehearse each of 401, 404, 429, and a timeout once, and then wire up production monitoring. Model availability and prices follow the model pricing page.

Related reading: