ModelSiteAPI

错误码

错误响应的几种形态、状态码与 type 取值、各入口的差异,以及哪些错误可以重试

这一页按代码实际行为整理;请求头、响应头、限流与余额处理等平台层面的行为见平台扩展与差异。先说两件事:

  • 请求经过两层,网关(鉴权、限流、余额、请求体检查)和路由层(选上游、调上游、故障切换)。两层生成的错误形态不完全一样,而且路由层会把上游返回的状态码原样带给你。
  • error.code 不可靠。网关生成的错误没有 code;路由层生成的 code 有时等于 type,有时是更细的值。分支判断请用 HTTP 状态码加 error.type,不要依赖 code。

每个响应都带 X-Request-ID 头(你自己传了就原样回显)。报问题时附上它。

怎么判断

  1. 看状态码。2xx 成功;4xx 一般是请求本身的问题,不要原样重试;429、5xx 才值得重试,见重试建议。
  2. 看响应体形态(见下节)。不要假设一定是 {"error": {...}}:/v1/messages 上是 Anthropic 风格的对象,原生入口的创建阶段错误是各自厂商的格式。
  3. 流式请求要看流本身。HTTP 已经返回 200 之后的失败只会出现在流里,状态码不会变,见流式中途失败。

错误结构

OpenAI 风格(默认)

/v1/chat/completions、/v1/responses、/v1/embeddings、图像、语音等入口,以及网关层的所有错误,都是这个形态:

{
  "error": {
    "type": "invalid_request_error",
    "message": "unknown model: foo-1"
  }
}
字段说明
error.type错误类别,见 type 取值
error.message说明文字,面向人,不要解析
error.code网关层错误没有这个字段;路由层错误有,可能等于 type,也可能是更细的值(如 no_upstream_available)。GET /v1/models/{id} 的 404 另带 param: null

没有单独标出出错参数的 error.param,出错的字段看 message。

Anthropic 风格(/v1/messages 与 /v1/messages/count_tokens)

{
  "type": "error",
  "error": { "type": "invalid_request_error", "message": "max_tokens is required and must be > 0" }
}

这两个入口上,网关层错误(鉴权、余额、限流、请求体过大、组织停用等)和路由层错误都是这一种形态,type 取 Anthropic 官方的名称:400 为 invalid_request_error,401 为 authentication_error,402 为 billing_error,403 为 permission_error,404 为 not_found_error,413 为 request_too_large,429 为 rate_limit_error,503 为 overloaded_error(当错误本身已是某个官方名称时保持不变),504 为 timeout_error,其余 5xx 为 api_error。

组织或团队停用

组织、团队被停用,或 Key 没有归属组织时,状态码是 403,响应体与其它网关错误一样是标准错误对象,形态随入口而定(/v1/messages 为 Anthropic 风格,其余入口为 OpenAI 风格,Gemini 入口为 Google 风格),type 为 permission_error,message 为 organization suspended、team suspended 或 API key is not attached to an organization。

原生入口的创建阶段错误

原生入口只有平台自己做的参数校验用厂商原生格式,其余错误(见下节"入口差异")仍是 OpenAI 风格。

入口参数校验错误的形态
/api/v1/services/aigc/*(百炼,含 Wan、HappyHorse、Qwen Image){"code": "InvalidParameter", "message": "..."};任务不存在时 {"code": "NotFound", ...}
/v1/contents/generations/tasks、/api/v3/contents/generations/tasks(方舟 Seedance){"error": {"code": "InvalidParameter", "message": "..."}};任务不存在时 code 为 NotFound
/v2/video_generation(MiniMax){"type": "error", "error": {"type": "bad_request_error", "message": "...", "http_code": "Bad Request"}};任务不存在时 type 为 not_found_error

状态码

状态码产生层触发条件你该怎么办
400网关请求里取不到 model(缺字段、请求体不是合法 JSON,或分块上传的请求体超限时也是这个提示);model 不是当前可调用的模型(unknown model: ...)检查请求体和模型名,不要重试
400路由层请求体绑定失败或校验失败(messages 为空、角色非法、Anthropic 缺 max_tokens 等),message 是具体原因按 message 修请求
400上游透传上游判定请求有问题(参数不支持、上下文超长、内容审核等)按 message 修请求
401网关没带 Authorization: Bearer ...;Key 格式不对(须以 sk-ms- 或旧版 sk-relay- 开头,且长度不少于 20);Key 不存在、已撤销或已过期(这三种返回同一句 invalid API key)检查请求头与控制台里的 Key 状态。x-api-key 头不被接受
402网关组织余额耗尽,或某个预算信封(Key / 成员 / 团队)额度用完。余额耗尽后,只读查询(GET /v1/models、视频任务和响应的查询等)仍可正常使用,只有会产生费用的请求返回 402充值或调整预算后再请求
403网关组织或团队被停用、Key 没有归属组织(permission_error);Key 的模型白名单不含该模型(model_access_error)联系组织管理员,不要重试
403上游透传上游返回 403,通常 type 为 permission_denied_error不是你的 Key 的问题,带 X-Request-ID 联系支持
404网关GET /v1/models/{id} 的模型不存在或未发布,code 为 model_not_found;/v1/videos* 已下线,code 为 endpoint_retired核对模型名 / 改用模型对应的原生入口
404路由层模型存在但当前没有任何上游配置(code: model_not_found);视频/响应任务的 ID 不存在或已过期(not_found,原生入口用各自格式)核对 ID;任务有查询期限
404框架路径不存在或方法不对:响应体是纯文本 404 page not found,不是 JSON核对路径和方法
413网关请求头声明的 Content-Length 超过上限(网关默认 50 MB,部署可调),invalid_request_error。公网入口前面的 nginx 另有一道 25 MB 上限,超过时由 nginx 直接返回 413,响应体是 HTML,不是 JSON缩小请求体,大文件别用 base64 内联;按 25 MB 以内准备请求
422上游透传平台自己不生成 422。上游返回时按上游状态码原样透传按 message 修请求
429网关触发 RPM 或 TPM 限流(rate_limit_error,message 固定为 too many requests,不区分是 RPM 还是 TPM),带 Retry-After;Realtime 并发会话超限也是 429(无 Retry-After)按 Retry-After 退避
429上游透传上游限流(含冷却期内只有一个上游的模型);带 Retry-After(上游给了就用上游的,否则默认 5)按 Retry-After 退避
429公网入口同一个来源 IP 请求过密(约 30 次/秒,允许突发约 100 次)时,入口 nginx 直接返回 429,响应体是 HTML,不带 Retry-After;与 Key 的 RPM 限流是两回事降低并发,指数退避
500网关网关构造上游请求失败(server_error)可重试;持续出现联系支持
500路由层其余未分类的内部错误(internal_error);视频、响应任务的查询或删除失败(上游返回 4xx 时也会统一成这个 500)。message 固定为 The request could not be completed; please retry later.,不回显内部原文同上
502网关连不上路由层,或 120 秒内没拿到路由层的响应头(server_error,message 为 upstream service unavailable)可重试,非流式的长请求改用 stream: true
502路由层上游网络层失败(连接、DNS、TLS、超时),type 为 bad_gateway,message 固定为 The upstream service is temporarily unavailable. Please retry.可重试
503网关见下方"503 的几种来源"见下方
503路由层没有可用上游:code: no_upstream_available;message 固定为 The upstream service is temporarily unavailable. Please retry later.,带 Retry-After(默认 5)稍后重试
408、504 等上游透传上游自己返回的状态码。embeddings 与 rerank 会把上游的 408/504 统一成 408 timeout_error,其余入口原样透传可重试

路由层返回的上游错误,来自最后一次尝试的那个上游:平台会先切换上游,全部失败后把最后一个上游的状态码和说明返回给你。所以同一个 401、402、403,既可能是网关对你的 Key 的判定,也可能是上游对平台账号的判定。网关的 401 文案是固定的几句(见上表),402 的 type 固定为 insufficient_quota(/v1/messages 上为 billing_error);不符合这些特征的,是上游透传,见下节。

503 的几种来源

typecodemessage 特征含义Retry-After
overloaded_error无gateway at capacity, retry later网关并发已满(默认 500 路上游请求,排队最多 10 秒)有,固定 5
service_unavailable无service temporarily unavailable, please retry shortly网关暂时无法保证 Key 撤销和停用及时生效,所以拒绝服务(出现在鉴权之前)有,固定 5
api_error无the platform cannot evaluate this key right now网关缺少判定这把 Key 所需的数据(刚启动或同步未完成)无
service_unavailableno_upstream_availableThe upstream service is temporarily unavailable. Please retry later.路由层选不出上游有,默认 5(路由层有明确等待时间时用它)
上游自己的 type视情况上游的文案上游返回 503(Anthropic 上游的 529 也会变成 503)无

这几种都值得重试,但只有第一种明确给出了等待时间。

type 取值

网关生成

type状态码说明
authentication_error401Key 缺失、格式错误或无效
model_access_error403Key 所属组织或团队的模型白名单不含该模型
insufficient_quota402余额或预算信封不足(/v1/messages 上为 billing_error);message 为 insufficient balance,预算信封触发时附 (budget envelope: ...)
rate_limit_error429RPM / TPM 限流,或 Realtime 并发会话超限
invalid_request_error400 / 404 / 413缺 model、未知模型、请求体过大、已下线路径
overloaded_error503网关并发已满
service_unavailable503配置同步中断
api_error503网关无法判定这把 Key
server_error500 / 502网关到路由层之间的故障

路由层生成

type状态码code说明
invalid_request_error400同 type请求绑定或校验失败
invalid_request_error404model_not_found模型下没有上游
service_unavailable503no_upstream_available没有可用上游
service_unavailable503upstream_cooling_down可用上游都处于临时冷却,稍后重试
bad_gateway502bad_gateway上游网络层失败
internal_error500internal_error未分类内部错误
not_found404同 type响应、视频任务的 ID 找不到

no_upstream_available 与 upstream_cooling_down 两个错误码于 2026-10-19 更名,旧名 no_suppliers_available / all_vendors_cooling_down 含义相同;若你的客户端按旧码判断,请同时匹配新旧两个名字。

上游错误经路由层透传

状态码取上游的,message 取上游的文案(会去掉请求 ID、内部端点 ID 等标识)。type 取决于入口和上游类型:

入口上游状态码type
chat / messages / responses,OpenAI 兼容类上游(多数国内供应商)任意api_error,状态码原样
chat / messages / responses,Anthropic 类上游400 401 403 404 429 500invalid_request_error authentication_error permission_denied_error not_found_error rate_limit_error internal_server_error;529 变 503 service_unavailable;其余 api_error
图像、视频创建(百炼、方舟这几类)400 401/403 404 429 500invalid_request_error authentication_error(注意 403 也映射成 401)not_found_error rate_limit_error internal_server_error;其余 api_error
embeddings、rerank按状态码和文案rate_limit_error、context_length_exceeded、content_policy_violation、invalid_request_error、authentication_error、permission_denied_error、not_found_error、timeout_error(408)、internal_server_error、service_unavailable、api_error

context_length_exceeded 和 content_policy_violation 只在 embeddings、rerank 上出现。对话类入口遇到上下文超长或内容审核,你收到的是 400 加 api_error 或 invalid_request_error,原因在 message 里。

各入口的差异

入口网关层错误路由层 / 上游错误流式中途失败
/v1/chat/completionsOpenAI 风格OpenAI 风格,含 codedata: {"error":{"message","type"}} 然后 data: [DONE]
/v1/messages、/v1/messages/count_tokensAnthropic 风格Anthropic 风格event: error,数据为 {"type":"error","error":{"type","message"}}
/v1/responsesOpenAI 风格OpenAI 风格,含 codeevent: error({"type":"error","code","message"})后跟 event: response.failed
/v1/embeddings、/v1/rerank、图像、语音OpenAI 风格OpenAI 风格,含 code不适用
视频创建与任务轮询(百炼、方舟、MiniMax 原生入口)OpenAI 风格参数校验与任务不存在用原生格式;选不到上游或上游调用失败仍是 OpenAI 风格不适用

视频与异步任务要注意:

  • 创建请求成功只表示任务已提交,HTTP 状态是 200。任务后来失败时,轮询接口仍返回 200:百炼入口里 output.task_status 为 FAILED,原因在 output.code 和 output.message;方舟、MiniMax 入口返回上游任务体,status 为 failed,错误字段是上游自己的。
  • 轮询时任务 ID 无效或过期,用的是原生入口各自的 404 格式;轮询时上游调用本身出错,则是 OpenAI 风格的 500 或 502。
  • /v1/videos、/v1/videos/generations 已下线,返回 404,code 为 endpoint_retired。视频只在各模型的原生入口提供。

GET /v1/responses/{id} 通过响应 ID 找回创建它的上游。ID 无法解码时是 400,找不到上游是 404(type: not_found)。DELETE /v1/responses/{id} 和 POST /v1/responses/{id}/cancel 不需要请求体,也不需要 model,网关直接放行到后端;它们不产生费用,余额耗尽时同样可用。

流式中途失败

流一旦开始,HTTP 状态已经是 200,之后的失败只能写进流里。三种情况:

  • 上游中途报错、连接中断、流被截断(没有收到结束事件就结束了)、或默认 4 分钟没有任何数据:按上表的入口格式发出一个错误事件,然后结束流。type 是上游的错误类型,网络层或截断统一为 server_error。
  • 组织余额在流进行中耗尽:网关切断流,并写入 data: {"error":{"type":"insufficient_quota","message":"balance exhausted"}} 和 data: [DONE]。这一帧在所有流式入口上都是这个 OpenAI 风格,包括 /v1/messages。
  • 你主动断开:没有任何错误事件。

处理方式:把"没有收到正常结束标志"当成失败。Chat Completions 是最后一个 chunk 没有 finish_reason 或出现了 error 帧,Anthropic 是没有 message_stop,Responses 是没有 response.completed。中途失败时,已经生成的部分仍按上游实际用量计费。

在收到第一个字节之前失败,平台会先自动切换上游,成功就正常返回,全部失败才返回一个带状态码的 JSON 错误。

重试建议

状态码重试?说明
400 401 402 403 404 413否原样重试结果不会变。402 充值后才会好
429是有 Retry-After 就按它等,没有就指数退避。被 TPM 限流时,Retry-After 可能比实际需要等待的时间短,退避要留余量
500 502 503 504 408是指数退避,加抖动,最多几次
任何状态码,但 type 为 api_error 且是 401 402 403否这是上游对平台账号的判定,不是你的 Key 或余额,重试没用,联系支持并附 X-Request-ID
import random, time

RETRYABLE = {408, 429, 500, 502, 503, 504}

def call_with_retry(send, tries=4):
    for i in range(tries):
        resp = send()
        if resp.status_code not in RETRYABLE or i == tries - 1:
            return resp
        wait = float(resp.headers.get("Retry-After", 2 ** i))
        time.sleep(wait + random.random())

重复调用与重复计费

  • 平台没有幂等键,也不会按请求内容去重。
  • 一次请求在平台内部切换上游,只有最终成功的那一次会计费,失败的尝试不计费。你看到的是一次成功或一次错误。
  • 你自己重试则是新的请求。如果上一次其实已经成功、只是响应没到你手里(客户端超时、连接被切断),重试会产生第二次生成和第二次计费。对话类请求副作用有限,可以接受;视频创建不能这样重试:创建请求遇到超时、502 或连接中断时,先确认任务有没有建出来,再决定是否重新创建,否则会出现两个任务、两份费用。
  • 流式请求中途失败不要整体重试成"同一次生成",已输出的部分已经计费,重试从头再来会再计费一次。需要续写就把已收到的内容放进上下文发新请求。
  • 非流式请求有两个相关的时间限制:网关等不到响应头 120 秒就断开并返回 502;路由层调用上游的总时限是非流式 10 分钟、流式 5 分钟。生成时间可能超过两分钟的请求请用 stream: true。

本页内容