# 错误码

> /v1 会返回的每一个错误码：触发条件、是否可重试、处理方式，以及两种格式的错误体。

来源：https://www.scirouter.cn/docs/errors · 更新于 2026-10-24

对话补全、向量与模型列表接口的错误体与 OpenAI 格式兼容，另带 `request_id` 与 `details`。`/messages` 使用 Anthropic 格式，见 [Anthropic 格式的错误体](#anthropic-格式的错误体)。

```json
{
  "error": {
    "message": "请求过于频繁，请稍后再试",
    "type": "rate_limit_error",
    "code": "rate_limited",
    "scirouter_code": "RATE_LIMITED",
    "request_id": "req_88a1",
    "details": { "retry_after_seconds": 12 }
  }
}
```

| 字段 | 说明 |
|---|---|
| `message` | 供人阅读的错误说明，措辞可能变更，不用于程序分支 |
| `type` | 按状态码映射的错误类别，粒度较粗，见 [type 与状态码](#type-与状态码) |
| `code` | 小写的平台错误码，程序按它分支。三个上游语义错误例外，取原厂兼容值（如 `context_length_exceeded`），见[上游语义错误](#上游语义错误) |
| `scirouter_code` | 大写的平台错误码，OpenAI 格式的错误体均返回。需要对全部错误统一分支时读取该字段 |
| `param` | 仅参数错误时返回，指出出错的字段 |
| `request_id` | 本次调用的编号，与响应头 `X-Request-Id` 相同 |
| `details` | 附加信息，如 `retry_after_seconds`、`limit`、`scope`。官方 SDK 忽略该字段，不影响兼容 |

返回 `details.retry_after_seconds` 时，响应头 `Retry-After` 必定取相同的值。

报障时提供 `request_id`，平台按它定位单次调用。控制台请求日志可按 `request_id` 查到对应记录，详情页的「复制报障信息」汇总排障所需的全部信息，见[可观测性](https://www.scirouter.cn/docs/observability)。

## 可重试的错误

按指数退避重试；响应带 `Retry-After` 时按其等待。重试须设置次数上限。

| 状态码 | code | 触发条件 | 处理方式 |
|---|---|---|---|
| 429 | `rate_limited` | 超出每分钟请求数、每分钟 token 数或并发请求数；上游厂商限流；达到套餐每日配额上限。见 [HTTP 429 的来源](#http-429-的来源) | 有 `Retry-After` 时按其等待，否则指数退避 |
| 429 | `upstream_saturated` | 上游线路的名额已满，排队未成功；`details` 带 `queue_position` 与 `queue_length` | 按 `Retry-After` 退避，或更换模型 |
| 502 | `upstream_error` | 上游返回 5xx；上游拒绝平台的凭证或找不到模型；响应无法解析；流意外中断（`details.provider_error.code` 为 `stream_interrupted`） | 指数退避 |
| 503 | `model_unavailable` | 线路暂时都无法接收请求（熔断、限额、并发已满），或模型的全站并发已满。`details.reason` 为 `endpoints_busy` 或 `model_busy`，带 `Retry-After` | 按 `Retry-After` 等待。不带 `Retry-After` 的 503 见[不可重试的错误](#不可重试的错误) |
| 504 | `upstream_timeout` | 上游超时。`details.timeout` 取 `connect`、`first_byte`、`idle`、`response`（非流式等待完整响应）、`total` 或 `upstream` | 指数退避；持续出现时调小 `max_tokens` 或改用流式 |
| 409 | `idempotency_conflict` | 请求带 `Idempotency-Key`，同一个键的请求仍在处理中 | 等待后重试，并设次数上限。同一 code 的另一种含义见[不可重试的错误](#不可重试的错误) |
| 500 | `internal` | 服务内部错误 | 指数退避；反复出现时提供 `request_id` 报障 |

## 不可重试的错误

重试不改变结果，须先修改请求或设置。

| 状态码 | code | 触发条件 | 处理方式 |
|---|---|---|---|
| 400 | `validation_failed` | 请求不合法，或上游拒绝请求而平台未识别其语义。具体情况见表下 | 按 `message` 与 `param` 修改请求 |
| 400 | `context_window_exceeded` | 输入（或输入加 `max_tokens`）超出模型的上下文窗口。`param` 为 `messages`，`code` 为 `context_length_exceeded`；两种来源见表下 | 缩短输入、调小 `max_tokens`，或换用窗口更大的模型，见[参数如何被处理](https://www.scirouter.cn/docs/params)「上下文窗口」 |
| 400 | `unsupported_param` | 参数或内容无法带到线路上，或远程图片无法取回。具体情况见表下 | 去掉 `param` 所指的参数或内容，或更换模型，见[参数如何被处理](https://www.scirouter.cn/docs/params) |
| 400 | `content_filtered` | 上游内容审核拒绝。`details.semantic` 为 `content_filtered`，`code` 为 `content_filter`；[图片接口](https://www.scirouter.cn/docs/images)上 `code` 为 OpenAI 图片接口的 `moderation_blocked` | 修改内容。各厂商审核标准不同，更换模型不一定有效 |
| 400 | `unsupported_protocol` | 模型所在线路的入口不支持该操作。目前只有一种情况：调用向量接口，而线路只有 Anthropic 入口（向量只走 `openai`、`custom`、`gemini` 入口，见[多厂商差异](https://www.scirouter.cn/docs/vendors)） | 更换模型 |
| 401 | `unauthenticated` | 未带 Key、Key 格式错误（常见原因是填入了其他厂商的 Key）或 Key 不存在 | 不自动重试。检查环境变量，值应为以 `sk-sr-` 开头的 SciRouter Key |
| 401 | `key_revoked` / `key_expired` | Key 已吊销或已过期 | 在控制台更换 Key |
| 401 | `account_suspended` | 账号已停用 | 联系平台 |
| 402 | `insufficient_quota` | 余额不足以预扣（按输入估算加输出上限预扣，充值余额大于 0 的账户输出只按预留估，见[认证与 API Key](https://www.scirouter.cn/docs/authentication)「预扣」），或此前结算使配额变为负数；带 `details.required_quota`，团队账户另带 `details.account_kind: "team"` | 充值（团队账户联系负责人）。`max_tokens` 小于平台设定的输出预留时，调小它可减少预扣 |
| 403 | `model_not_allowed` | 模型不在白名单中；`details.scope` 为 `key`、`project` 或 `plan` | 修改白名单、更换 Key 或更换模型 |
| 403 | `model_restricted` | 受限模型，本次调用所在的工作区未获授权 | 使用已获授权的团队项目下的 Key |
| 403 | `team_suspended` | Key 属于团队项目，该团队已停用 | 联系团队负责人 |
| 404 | `model_not_found` | 模型 id 不存在，或是对调用方不可见的受限模型 | 检查 id（区分大小写），以 `GET /models` 的返回为准 |
| 404 | `project_not_found` / `team_not_found` | 前者：Key 所属项目已不存在；后者：Key 的所有者已不在该团队 | 更换 Key |
| 409 | `idempotency_conflict` | 同一个 `Idempotency-Key` 用于不同的请求体，通常是代码复用错了键 | 检查键的生成与复用。该 code 与「处理中」的 409 相同，仅 `message` 不同；有限次重试后仍返回 409 时按本行处理 |
| 409 | `idempotency_conflict`（`details.reason = result_not_replayable`） | [图片接口](https://www.scirouter.cn/docs/images)不保存 `b64_json` 与流式结果：同一个键的请求已完成，无法重放 | 需要重新生成时使用新的键 |
| 413 | `payload_too_large` | 请求体超过上限（默认 4 MB） | 拆分后再发送 |
| 422 | `project_archived` | Key 所属项目已归档 | 使用不属于该项目的 Key |
| 429 | `key_quota_exceeded` | 该 Key 的月度上限不足（已用量加本次估算超过上限）；不带 `Retry-After` | 下月恢复。上限创建后不可修改，急需时更换 Key |
| 429 | `project_budget_exceeded` | 项目的月预算已用完；`Retry-After` 指向下月 1 日 | 在控制台调高项目预算 |
| 503 | `model_unavailable` | 本次请求在该模型上无法完成（如带 `tools` 而没有支持工具调用的线路、超过单次上限），或模型已下线、维护中、尚未定价。不带 `Retry-After`，带响应头 `x-should-retry: false`；`details.reason` 见 [HTTP 503 的 details.reason](#http-503-的-details-reason) | 重试无效。按 `details.reason` 修改请求或更换模型 |

`validation_failed` 的触发条件：

- 请求体不是 JSON 对象、字段类型错误、缺少 `model`、`messages` 为空、`stop` 类型错误；
- `max_tokens` 超过模型或套餐的单次上限（`details.limit`）；
- 输入的 token 估算超过套餐的每分钟上限：`details.reason` 为 `plan_tpm_exceeded`，见 [HTTP 400 的 details.reason](#http-400-的-details-reason)；
- `metadata`、托管工具声明或缓存相关请求头写法错误；
- `Idempotency-Key` 超长；
- 上游拒绝请求，而平台未识别是哪种语义：`details.source` 为 `upstream`，带 `provider_error`。已识别语义的归入 `context_window_exceeded`、`unsupported_param`、`content_filtered`。

`context_window_exceeded` 的两种来源：

- 平台发出前估算得出：带 `details.limit`、`details.estimated`、`details.max_tokens`；
- 上游报告：`details.semantic` 为 `context_window_exceeded`，厂商文案含数字时才带 `limit` 与 `estimated`。

`unsupported_param` 的触发条件：

- 契约类参数在该模型的所有线路上都无法带到（`details.param`、`details.cause`）；
- 上游明确拒绝某个参数，而平台无法去掉它（`details.semantic` 为 `unsupported_param`，`code` 为 `unsupported_parameter` 或 `unsupported_value`）；
- 请求含只能原样转发的内容，而没有可转发的线路（`details.reason` 为 `unsupported_content`，`details.unsupported_content` 列出这些内容）；
- 远程图片无法取回（`details.reason` 为 `media_fetch_failed`）。

## `type` 与状态码

`type` 按状态码映射，与 OpenAI 的惯例一致。程序分支使用 `code`。

| `type` | 状态码 |
|---|---|
| `authentication_error` | 401 |
| `insufficient_quota` | 402 |
| `permission_error` | 403 |
| `rate_limit_error` | 429 |
| `upstream_error` | 502、503、504 |
| `server_error` | 其他 5xx |
| `invalid_request_error` | 其他 4xx |

## 上游语义错误

平台将上游错误中的三种常见语义归为固定的 code：`context_window_exceeded`（上下文超长）、`unsupported_param`（参数不支持）、`content_filtered`（内容审核）。三者均为 400，不可重试，须修改请求。错误体分两层：

| 平台码（`scirouter_code`） | OpenAI 格式的 `error.code` | Anthropic 格式的 `message` |
|---|---|---|
| `CONTEXT_WINDOW_EXCEEDED` | `context_length_exceeded`，`param` 为 `messages`，`message` 以 `This model's maximum context length is {limit} tokens. However, …` 开头 | 输入本身超出时含 `prompt is too long: {estimated} tokens > {limit} maximum`；输入未超出、加上 `max_tokens` 后超出时含 ``input length and `max_tokens` exceed context limit: {estimated} + {max_tokens} > {limit}``；上游报告且无法提取数字时只有 `prompt is too long` |
| `UNSUPPORTED_PARAM` | `unsupported_parameter`（取值不支持时为 `unsupported_value`），`param` 为参数名 | 写明参数名与原因 |
| `CONTENT_FILTERED` | `content_filter` | — |

- 平台码在 `error.scirouter_code`（OpenAI 格式）或 `error.code`（Anthropic 格式，小写）中；`details` 照常带 `param`、`limit`、`estimated`、`semantic`、`provider_error`。
- `code` 只取原厂可识别的值，供现有客户端使用：Claude Code 按 `prompt is too long` 中的两个数字裁剪历史、按 `exceed context limit` 调小 `max_tokens`；Codex 仅在 `response.failed` 中出现 `context_length_exceeded` 时压缩对话；不少 OpenAI 兼容客户端按 `context_length_exceeded` 或 `unsupported_parameter` 分支。
- 无法带到线路上的提示类参数默认由网关去掉并留痕，不返回 400，见[参数如何被处理](https://www.scirouter.cn/docs/params)。
- 上下文超长通常由平台在发出前估算得出（带 `details.estimated`），此时不预扣、不占名额。
- 上游不支持某个参数时，平台先尝试去掉该参数后重发（响应头 `X-SciRouter-Param-Actions` 中记为 `healed`）。返回 400 表示该参数无法去掉，或没有可换的线路。

## Anthropic 格式的错误体

`/messages` 与 `/messages/count_tokens`（以及带 `anthropic-version` 请求头的 `/models`）返回 Anthropic 格式的错误体，鉴权失败时也是如此，Anthropic SDK 可直接识别：

```json
{
  "type": "error",
  "error": {
    "type": "overloaded_error",
    "message": "…",
    "code": "model_unavailable",
    "details": { "reason": "endpoints_busy" }
  },
  "request_id": "req_88a1"
}
```

状态码、`code` 与 `details` 与[可重试的错误](#可重试的错误)、[不可重试的错误](#不可重试的错误)两张表完全相同（`error.code`、`error.details` 为扩展字段），`request_id` 位于顶层。`error.type` 按状态码映射，平台策略类拒绝例外，取 `policy_blocked`：

| `error.type` | 状态码 |
|---|---|
| `invalid_request_error` | 400，以及 422 等其余 4xx |
| `authentication_error` | 401 |
| `billing_error` | 402 |
| `permission_error` | 403 |
| `not_found_error` | 404 |
| `conflict_error` | 409 |
| `request_too_large` | 413 |
| `rate_limit_error` | 429 |
| `api_error` | 500、502，以及不带 `Retry-After` 的 503（本次请求在该模型上无法完成） |
| `overloaded_error` | 带 `Retry-After` 的 503（线路或模型暂时繁忙） |
| `timeout_error` | 504 |
| `policy_blocked` | 平台策略类拒绝，不按状态码映射，见下表 |

`policy_blocked` 覆盖下列 code。状态码保持各自的 401、402、403、404、422 或 429，并带 `x-should-retry: false`。修改请求或重试均无效，需人工处理；Claude Code 直接展示该错误，不重试。

| 类别 | code |
|---|---|
| 配额 | `insufficient_quota`、`key_quota_exceeded`、`project_budget_exceeded` |
| 权限与受限模型 | `model_not_allowed`、`model_restricted` |
| Key、账号、团队、项目的状态 | `key_revoked`、`key_expired`、`account_suspended`、`team_suspended`、`project_not_found`、`project_archived` |

模型暂时不可用时仍返回 503，不使用 Anthropic 的 529。Anthropic SDK 对 5xx 自动重试，带 `x-should-retry: false` 的除外。程序分支使用 `error.code`。

以下两项遵循 Claude Code 的网关约定：

- 能力类拒绝带固定标记：平台自身拒绝、且客户端关闭对应能力即可恢复的 400，在 `message` 末尾追加 `capability_rejected: <class>`，`details.capability_rejected` 取相同值。Claude Code 收到后关闭该能力并重发。class 取值见下表。
- 转发上游的 4xx 时，厂商原文保留在 `message` 中（前缀为「上游拒绝了请求：」），按子串匹配的客户端不受影响。

| class | 含义 |
|---|---|
| `prompt_too_long` | 输入超出窗口；或输入估算超过套餐每分钟 token 数（`details.reason` 为 `plan_tpm_exceeded`），此时 `message` 同样以 `prompt is too long: N tokens > M maximum` 开头，M 为套餐每分钟上限 |
| `max_tokens_context_overflow` | 输入加 `max_tokens` 超出窗口 |
| `thinking_signature` | 思考块的签名被拒 |
| `structured_outputs_unsupported` | 结构化输出（`response_format`）被拒 |
| `effort_unsupported` | 思考参数被拒 |
| `image_block` | 图片输入被拒 |
| `document_block` | 文件输入被拒 |

## HTTP 503 的 `details.reason`

`model_unavailable` 同时覆盖「暂时繁忙」与「本次请求在该模型上无法完成」两类情况，以 `details.reason` 区分。`details.reason` 为固定的英文码，可用于程序分支。

| reason | 含义 | 带 `Retry-After` | 处理方式 |
|---|---|---|---|
| `endpoints_busy` | 该模型的线路暂时都无法接收请求（熔断、限额或并发已满） | 是 | 按 `Retry-After` 等待 |
| `model_busy` | 该模型在平台上的并发请求数已满 | 是 | 按 `Retry-After` 等待 |
| `tools_unsupported` | 请求带 `tools`，而该模型没有支持工具调用的线路 | 否 | 去掉 `tools`，或更换模型 |
| `streaming_unsupported` | 请求为流式，而该模型没有支持流式的线路 | 否 | 改用非流式，或更换模型 |
| `input_too_large` | 预计 token 数（输入加 `max_tokens`）超过线路的单次上限 | 否 | 缩短输入、调小 `max_tokens` |
| `no_capable_endpoint` | 没有一条线路同时满足本次请求的要求（工具调用、流式、长度） | 否 | 更换模型 |
| `no_endpoint` | 该模型当前没有可用的线路 | 否 | 更换模型，稍后再查看模型状态 |
| `model_offline` | 模型已下线、维护中或尚未定价 | 否 | 更换模型，稍后再查看模型状态 |

**不带 `Retry-After` 的 503 重试无效。** 这类响应带 `x-should-retry: false`。OpenAI 与 Anthropic 的官方 SDK 以及 Claude Code 先读取该响应头，值为 `false` 时停止自动重试并直接返回错误；自行实现的重试逻辑也应读取该响应头。

请求含只能原样转发的内容、而没有可转发的线路时，返回 400 `unsupported_param`（`details.reason` 为 `unsupported_content`），不再归入 `no_capable_endpoint`。503 只用于等待后可恢复或更换模型可解决的情况。

## HTTP 400 的 `details.reason`

`validation_failed` 多数情况下不带 `details.reason`，按 `message` 与 `param` 处理即可。下列情况带固定的 reason，适用的接口见各行：

| reason | 含义 | 处理方式 |
|---|---|---|
| `server_tool_unsupported` | `/messages` 或 `/responses` 的请求使用了厂商的服务端工具或连接器（`web_search_*`、`web_fetch_*`、`code_execution_*`、`mcp_servers`、`container` 等） | 去掉这些工具，改用自定义工具 |
| `price_param_unsupported` | 请求带了会使厂商按另一档单价收费的参数（`details.params` 列出），而平台未上架对应的模型变体 | 去掉这些参数，或改用变体，见 [Messages](https://www.scirouter.cn/docs/messages) |
| `sub_model_unpriced` | `/messages` 的 advisor 工具或 `fallbacks` 列表引用的模型未在平台上架或未定价（`param` 指向该字段）。无权调用该模型时，与直接调用它一样返回 403 | 换成平台上已定价的模型（正名或别名），见 [Messages](https://www.scirouter.cn/docs/messages)「计费」 |
| `stateful_unsupported` | `/responses` 带了 `previous_response_id`、`conversation`、`prompt` 或 `item_reference`。平台不保存响应，没有可引用的状态 | 将完整的对话历史放入 `input`，见 [Responses](https://www.scirouter.cn/docs/responses) |
| `background_unsupported` | `/responses` 带了 `background: true` | 去掉该参数，改为同步调用 |
| `plan_tpm_exceeded` | 输入的 token 估算本身超过了套餐每分钟的 token 数，无论等多久都发不出去（`param` 为 `messages`；[向量](https://www.scirouter.cn/docs/embeddings)为 `input`）。Anthropic 格式的 `message` 以 `prompt is too long:` 开头并带 `capability_rejected: prompt_too_long`，Claude Code 据此尝试自动压缩对话后重发；对话太长、压缩请求本身也超过上限时，压缩会失败。`details.limit` 为套餐每分钟上限，`details.estimated` 为输入估算。`max_tokens` 不参与这一判定 | 缩短输入（如压缩对话历史），或升级套餐 |
| `model_kind_mismatch` | 模型种类与接口不符：对话类接口（`/chat/completions`、`/responses`、`/messages`、`/embeddings`）调用了生图等媒体模型，或[图片接口](https://www.scirouter.cn/docs/images)调用了非生图模型（此前对话接口调用生图模型返回 503） | 按 `/models` 的 `scirouter.kind` 调用对应的接口 |
| `edit_unsupported` / `variations_unsupported` | 该生图模型不支持改图或不支持变体（见 `scirouter.image.edit` 与 `variations`） | 更换模型 |
| `size_multiple_of`、`size_ratio`、`size_max_edge`、`size_min_pixels`、`size_max_pixels`、`size_not_preset`、`size_auto_not_allowed`、`size_format` | 图片的 `size` 不符合模型 `scirouter.image.sizes` 的规则 | 按 `sizes` 修改尺寸 |

`unsupported_param` 与 `context_window_exceeded` 的 `details.reason` 同样固定：

| reason | code | 含义 | 处理方式 |
|---|---|---|---|
| `unsupported_param` | `unsupported_param` | 契约类参数无法带到线路上：`details.param` 为参数名，`details.cause` 为原因，取值见下表 | 去掉该参数，或更换模型 |
| `unsupported_content` | `unsupported_param` | 请求含只能原样转发的内容（Anthropic 格式的 `search_result`、按需压缩、advisor 工具等；Responses 的 `input_file`、厂商定义的客户端工具等），`details.unsupported_content` 列出这些内容，而该模型没有可原样转发的线路 | 去掉这些内容，或更换模型 |
| `media_fetch_failed` | `unsupported_param` | 平台无法取回远程图片（非公网地址、过大、超时、数量过多） | 改为 data URL 内联，或更换地址 |
| `context_window` | `context_window_exceeded` | 平台发出前估算出输入（加 `max_tokens`）超出窗口；`details.scope` 为 `endpoint` 时为线路级窗口 | 缩短输入、调小 `max_tokens` |

| `details.cause` | 含义 |
|---|---|
| `feature_missing` | 模型未声明对应能力 |
| `rule_unsupported` | 模型的请求规则不接受该参数 |
| `not_carried` | 所有线路都无法带到，`details.params` 列出全部这类参数 |
| `strict` | 调用方通过请求头要求严格处理，见[参数如何被处理](https://www.scirouter.cn/docs/params) |

## HTTP 429 的来源

`rate_limited` 与另外两个配额类 code 的区别：

| code | 来源 | `details` | `Retry-After` |
|---|---|---|---|
| `rate_limited` | 每分钟请求数、每分钟 token 数或并发请求数超限 | `scope`：`personal`（账号）、`key`（该 Key）或 `team`（团队项目下的 Key 按团队限额计，成员共用） | 通常为秒级 |
| `rate_limited` | 套餐每日配额上限；`message` 为「今日用量已达套餐上限」 | `limit_quota`、`spent_quota` | 指向次日零点（平台时区） |
| `key_quota_exceeded` | Key 的月度上限 | — | 不带；下月恢复 |
| `project_budget_exceeded` | 项目的月预算 | — | 指向下月 1 日 |

每分钟 token 数在请求开始时按「输入估算 + 输出预留」计入，输出预留是 `max_tokens` 与平台设定值中的较小者；请求结束后按实际用量多退少补，实际输出超过预留的部分补记。因此 `max_tokens` 写得大不会被提前拒绝，但同一分钟里的长输出会让后续请求收到 429。

按 `code` 与 `details` 分支，不只看状态码。等待时长以 `Retry-After`（或 `details.retry_after_seconds`）为准。

## 重试策略

网关内置故障转移：默认在上游超时、返回 5xx 或被上游限流时，自动转到该模型的下一条可用线路，最多再转 2 次，总耗时不超过 60 秒（各模型可单独配置）。只有一条线路的模型、已开始输出的流式请求不做转移。

因此调用方收到 5xx 时，网关通常已尝试过其他线路；尝试次数见成功响应中的 `scirouter.attempts` 或响应头 `X-SciRouter-Attempts`。客户端的重试使用指数退避，不立即重发。

**非流式请求重试时带同一个 `Idempotency-Key`**，首次请求实际已成功时不会重复扣费。前提是首次请求未被客户端先断开：客户端断开的请求由服务端取消且不保存结果，见[缓存与幂等](https://www.scirouter.cn/docs/caching)。

官方 SDK 默认自动重试 429 与 5xx，不区分 `code`，见 [SDK 与框架](https://www.scirouter.cn/docs/sdks)「重试与超时」。

## 流式响应中的错误

流式响应可能在已输出部分内容之后出错。此时 HTTP 状态码已是 200，错误以带 `error` 字段的分片出现在流中，随后流直接结束，不再发送 `data: [DONE]`：

```text
data: {"id":"chatcmpl-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":"这段序列的"}}]}

data: {"error":{"message":"上游模型服务响应超时","type":"upstream_error","code":"upstream_timeout","request_id":"req_88a1","details":{"timeout":"idle"}}}
```

只检查 HTTP 状态码会把截断的回答当作完整回答。三种格式的流式结束标志与出错方式：

| 接口 | 正常结束 | 输出开始后出错 |
|---|---|---|
| 对话补全（`/chat/completions`） | `data: [DONE]` | 带 `error` 字段的分片，之后没有 `[DONE]` |
| `/messages`（Anthropic 格式） | `message_stop` 事件，没有 `[DONE]` | `event: error` 事件，内容为 [Anthropic 格式的错误体](#anthropic-格式的错误体)，随后断开 |
| `/responses` | `response.completed` 或 `response.incomplete` 事件，之后一行 `[DONE]` | `event: response.failed` 事件，`response.error` 带 `code` 与 `message` |

**未收到正常结束标志即结束的流，一律按失败处理。**

上下文超长例外：`/responses` 的流式调用无论在开流前还是开流后判定超长，均返回 HTTP 200 与 `response.failed` 事件（`response.error.code` 为 `context_length_exceeded`），Codex 只在收到该事件时压缩对话。非流式调用仍返回 HTTP 400。

流中错误帧的 `code` 只取原厂可识别的值，平台码仍在 `scirouter_code`：

| 流中的 `code` | 对应情况 |
|---|---|
| `rate_limit_exceeded` | 限流与上游满载 |
| `insufficient_quota` | 配额类错误 |
| `server_is_overloaded` | 带 `Retry-After` 的 503 |
| `server_error` | 其余 5xx |
| `context_length_exceeded` 等 | 上游语义错误，见[上游语义错误](#上游语义错误) |

## 未知路径

请求 `/v1` 下不存在的路径（如 `/v1/completions`）时返回 404，错误体为站内接口的格式（大写的 `NOT_FOUND`），与本页其他错误体不同。官方 SDK 同样抛出「未找到」异常。出现该错误时检查请求路径与 `base_url`，确认没有多写或少写一段 `/v1`。
