Moonshot API 的报错不能只看状态码。同样是 429,可能是集群过载、账户限流,也可能是余额不足;同样是 401,可能是 Key 写错,也可能是中国站和国际站混用。2026 年平台入口迁移和旧模型下线,又让 404 明显增多。

本文按“先定位、再分类、后修复”的顺序,拆解 401、404、429、上下文超长和超时五类问题,给出可复用的重试代码和支持工单清单。模型与价格以站内模型价格为准。

说明:Moonshot、Kimi 是其权利人的商标。错误类型、限流档位和下线时间可能调整,本文以 2026 年 10 月的官方文档和常见情况为例,最终以官方文档为准。

一、先固定三个字段

排障时先收集三样东西:HTTP 状态码、error.type、请求标识。Moonshot 的错误响应通常包含 error.message 和 error.type,具体字段以当前接口返回为准。请求标识可能出现在错误体、响应头或控制台日志中,不同版本位置不同,不要假设只有一种来源。

日志至少记录:时间(带时区)、状态码、error.type、模型名、Base URL 所属站点、是否流式、SDK 版本、重试次数、usage 和请求标识。不要记录完整 Key,也不要记录含敏感信息的提示词。

有了这三样,才能判断问题出在配置、账号还是服务端。下面逐类展开。

二、401:先查站点,再查 Key

Moonshot 分中国站和国际站:中国站入口 platform.kimi.com,接口 https://api.moonshot.cn/v1;国际站 platform.kimi.ai,接口 https://api.moonshot.ai/v1。两站账号、余额、Key 完全独立,拿中国站 Key 调国际站地址会返回 401 invalid_authentication_error。

按这个顺序排查:

  1. Key 是否来自当前 Base URL 对应的站点,而不是另一个站或另一个账号。
  2. 是否混用了开放平台 Key 和 Kimi Code 等其他产品线的 Key,两者不通用。
  3. 请求头是否为 Authorization: Bearer <key>,值前后有没有空格、换行或引号。
  4. 环境变量是否真的加载,可以只打印 Key 的前几位确认。
  5. Key 是否被删除、轮换,或项目权限已被回收。
  6. 本地是否还残留旧代理、旧环境变量或路由工具的配置,覆盖了当前请求。

错误类型上,invalid_authentication_error 多指 Key 格式或站点不匹配,incorrect_api_key_error 多指 Key 缺失或错误。两者都先修凭证,不要急着重试。

三、404:多数是模型下线,不是接口消失

2026 年最容易被忽略的 404 来源是模型生命周期。官方模型页列出的下线记录包括:

  • moonshot-v1 全系列,含 moonshot-v1-8k、-32k、-128k、-auto 和视觉预览版,2026 年 8 月 31 日下线,推荐迁移到 kimi-k3。
  • kimi-k2 系列,含 kimi-k2-0905-preview、kimi-k2-0711-preview、kimi-k2-turbo-preview 和思考版,2026 年 5 月 25 日下线。
  • kimi-latest 于 2026 年 1 月 28 日下线,kimi-thinking-preview 于 2025 年 11 月 11 日下线。

其他常见 404 原因:

  • OpenAI SDK 没有设置 base_url,请求发到了默认的 OpenAI 地址,返回模型不存在。
  • 模型名拼写错误,或账号档位无权访问该型号。
  • 路径多了或少了 /v1,或客户端把 Base URL 和完整路径拼重。
  • 中国站与国际站可用的模型名不同。

用同一个 Key 拉模型列表,确认账号实际能看到什么:

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

列表里没有的型号不要靠猜。模型列表能返回、聊天接口仍 404 时,重点检查路径拼接和客户端配置。

四、429:三种类型,处理方式完全不同

429 是排查里最容易误判的一类。先看 error.type:

error.type 含义 能否重试 处理方式
engine_overloaded_error 集群过载,容量紧张 可以 按 Retry-After 退避,降低并发
rate_limit_reached_error 组织级并发、RPM、TPM 或 TPD 超限 部分可以 降速、等待、提升账户档位
exceeded_current_quota_error 欠费、余额不足、代金券失效 不要重试 检查余额并充值

Moonshot 的限流档位按账户累计充值额划分 Tier0 到 Tier5,充值赠券通常不计入累计额。档位同时约束并发数、每分钟请求数、每分钟 Token 数和每天 Token 数:低档位并发可能只有个位数,高档位可到百级并发;RPM 从个位数到数百,TPM 从几十万到数百万。Tier0 还有每日 Token 上限,超限后通常要等次日重置。

几个容易踩的坑:

  • OpenAI SDK 默认会对 408、409、429 和 5xx 自动重试,最多共三次。低档位账户一次失败可能被放大成多次请求,很快耗尽 RPM。生产环境要显式设置 max_retries。
  • 联网搜索等工具有独立的 QPS 限制,和聊天接口的 RPM、TPM 分开计算,超限同样返回 429。
  • 被 429 中断的请求通常不计费,但重试成功后会正常计费,不要因为“不扣费”就无限重试。
  • 限额和档位对不上时,先确认是否用了别的账号的 Key。

五、400:上下文超长与参数错误

上下文超长通常返回 400 invalid_request_error,错误消息会提示输入 Token 超限。注意判断口径是“输入 + 输出上限”是否超过模型窗口,而不是只看输入。

常见触发方式:

  • 历史消息无限增长,多轮对话从未裁剪。
  • 把整份文档塞进 1M 上下文,同时又设置了很大的输出上限。
  • 文件接口上传超过 100MB、上传空文件,或 purpose 取值不在允许列表。
  • 输出触发了 content_filter,这类过滤也可能由模型输出触发,不只检查输入。

处理顺序是:先估算输入 Token,再给输出留空间;长文档分段摘要并保留引用;多轮对话做滑动窗口;结构化输出用工具调用,减少无效长文本。

另外,finish_reason=length 不是报错,而是输出达到了上限。需要更长结果时,分段请求或使用续写能力,不要直接把上限调到超过模型允许值。

六、超时、499 与流式

Moonshot 的网关对非流式请求有等待上限,官方文档提到 504 可能在 900 秒后出现。长文生成、长文档分析和代码 Agent 最容易遇到。

按这个顺序处理:

  1. 非流式改流式,设置 stream=True,让连接持续有数据返回。
  2. 连接超时设短,读取超时按最长生成时间设置,不要沿用 SDK 默认值。
  3. 检查公司代理、网关和本地路由工具是否提前断开连接,这类中断可能表现为 499 client_closed_request。
  4. 用输出上限控制单次生成长度,超长任务拆分。
  5. 流式场景看首 Token 延迟;TTFT 突然升高通常是上游拥塞或提示词变长。
  6. 记录每次超时的请求标识和耗时,区分模型慢、网络慢还是代理慢。

流式不会降低单价,但能减少“等到超时再重试”的重复消耗。读取超时不要沿用非流式的短值,否则连接会在正常生成时被客户端自己切断。

七、重试与退避怎么写

重试只适合瞬时错误。401、403、404、内容安全和余额不足不要自动重试;429 要先分类;5xx 可以退避。已经产生副作用的业务,先用幂等键或状态查询确认是否执行过。

import random
import time
from openai import OpenAI, APIStatusError, RateLimitError

client = OpenAI(
    api_key="你的密钥",
    base_url="https://api.moonshot.cn/v1",
    max_retries=0,  # 关闭 SDK 自动重试
)

RETRYABLE_TYPES = {"engine_overloaded_error", "server_error",
                   "server_unavailable", "client_closed_request"}

def ask(prompt: str, retries: int = 4) -> str:
    for attempt in range(retries):
        try:
            resp = client.chat.completions.create(
                model="kimi-k3",
                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("余额或额度不足,先充值")
            if etype == "rate_limit_reached_error":
                raise RuntimeError("账户限流,降低并发或提升档位")
            wait = min(2 ** attempt, 20) + random.random()
            print(etype or "overloaded", "等待", round(wait, 1), "秒")
            time.sleep(wait)
        except APIStatusError as exc:
            if exc.status_code in (401, 403, 404):
                raise
            if exc.status_code >= 500:
                time.sleep(min(2 ** attempt, 20) + random.random())
            else:
                raise
    raise RuntimeError("重试次数已用完")

print(ask("说明重试的适用边界"))

有 Retry-After 响应头时优先按它等待,再叠加随机抖动,避免多实例同时重试造成二次拥塞。重试次数要有上限,并把最终失败写入告警。

八、找支持前准备什么

  1. 发生时间,带时区和年份,精确到秒。
  2. 请求标识、响应 id 和 usage 字段。
  3. 模型名、Base URL、站点(中国站或国际站)、是否流式。
  4. HTTP 状态码、error.type 和完整错误消息。
  5. SDK 与客户端版本、重试配置、是否经过代理或网关。
  6. 最小可复现请求,一条 curl 即可。
  7. 账单或用量记录,用于核对是否重复计费。
  8. 脱敏后的日志,删除 Key、用户数据和敏感提示词。

先自己用直连 curl 复现一次,再把直连和网关的结果分开提交,能显著缩短定位时间。

常见问题

429 重试会重复扣费吗?

被 429 拒绝的请求通常不计费;重试成功后按正常请求计费。真正需要担心的是 SDK 自动重试把一次业务请求放大成多次,造成请求数和费用同时上升。

昨天还能用的模型,今天怎么 404 了?

先查官方模型页的下线记录。moonshot-v1 系列已于 2026 年 8 月 31 日下线,kimi-k2 系列和 kimi-latest 也已停止维护,按官方建议迁移到 kimi-k3。

429 提示余额不足,还需要退避重试吗?

不需要。exceeded_current_quota_error 属于账户余额或额度问题,重试不会恢复,先检查余额、欠费状态和代金券有效期。

已经用了流式,为什么还会超时?

流式降低的是首包等待,不保证连接永远不断。检查代理的 idle timeout、读取超时、输出上限和网络稳定性;也可能是上游长时间没有新 Token,触发中间设备断开。

直连正常、走网关报错,怎么判断责任方?

用同一把 Key、同一个模型、同一条请求分别打直连和网关,比较状态码、error.type、请求标识和耗时。直连成功而网关失败,重点查网关的路径、鉴权、超时和重试配置。

下一步

先在中商起航 AI 网关创建测试 Key,把 401、404、429 和超时各演练一次,再接入生产监控。可用型号与计费以模型价格为准。

相关阅读: