# 故障排查

URL: https://docs.router.ezat.io/zh/troubleshooting

> 按症状列出 EZAT Router 的常见问题（base URL 错误、401、402、未知模型、429 和 529、工具不使用你的设置、流式输出中断），以及原因和解决方法。

## 何时阅读本页

请求或工具出错时使用本页。在下面找到对应的状态码或症状；每一项都给出了原因和解决方法。完整的错误类型列表见[错误](https://docs.router.ezat.io/zh/reference/errors.md)。

先做两个快速检查，可以缩小大多数问题的范围：

- **请求到达 EZAT Router 了吗**？用有效 key 发出的每个 Messages 或 Chat Completions 请求，都会在几秒钟内出现在控制台的**用量**页面上，包括被拒绝的请求（状态为**已拒绝**）。如果什么都没有出现，说明工具把请求发到了别处，或者没有带上有效的 key。
- **错误是哪种格式**？API 错误带有错误 `type`，例如 `{"type":"error","error":{"type":"not_found_error",…}}` 或 `{"error":{"code":"model_not_found",…}}`。如果响应体类似 `{"statusCode":404,"message":"…"}`，说明 URL 路径本身就错了。

## Base URL

### 404 并提示 `Cannot POST /v1/v1/messages`

**原因**：base URL 以 `/v1` 结尾。Anthropic SDK 和 Claude Code 会自己加上 `/v1/messages`，所以路径重复了。

**解决方法**：使用 `https://api.router.ezat.io`，后面不加任何内容：`ANTHROPIC_BASE_URL=https://api.router.ezat.io`、`base_url="https://api.router.ezat.io"`。

### OpenAI 客户端或工具返回 404

响应体是 `{"statusCode":404,…}`，消息类似 `Cannot POST /v1/chat/completions` 或 `Cannot POST /openai/chat/completions`，或者只有 `Not Found`。

**原因**：OpenAI base URL 缺少 `/openai/v1`，或者只写了其中一部分。OpenAI 客户端会在 base URL 后面加上 `/chat/completions` 和 `/models`。

**解决方法**：原样使用 `https://api.router.ezat.io/openai/v1`，例如 `OpenAI(base_url="https://api.router.ezat.io/openai/v1")` 或 `OPENAI_BASE_URL=https://api.router.ezat.io/openai/v1`。见 [OpenAI 兼容 base URL](https://docs.router.ezat.io/zh/openai/base-url.md)。

## 认证

### 401 缺少 API key

消息为 `Missing API key. Send it in the x-api-key or Authorization: Bearer header.`

**原因**：没有收到 key。请求头缺失或拼写错误，或者本应保存 key 的环境变量在发出请求的进程中为空。从 Dock、开始菜单或 IDE 启动的应用，读不到在终端中 export 的变量。

**解决方法**：以 `x-api-key` 或 `Authorization: Bearer` 发送 key。在运行工具的同一个 shell 或应用中检查变量是否已设置，同时不打印 key：

```bash
printf 'length %s, prefix %s\n' "${#EZAT_API_KEY}" "${EZAT_API_KEY:0:8}"
```

应该输出 `length 48, prefix ezat_sk_`。

### 401 无效的 API key

**原因**：收到的值不是有效的 EZAT Router key：

- 输错了、复制不完整，或者 key 中间有引号、空格或换行（两端的空格会被忽略）；
- 其他服务商的 key，例如 Anthropic 或 OpenAI 的 key；
- 同时发送了两个 key。当请求同时带有 `x-api-key` 和 `Authorization` 时，EZAT Router 读取 `x-api-key`。如果工具里还设置着旧的 `ANTHROPIC_API_KEY`，它会以 `x-api-key` 发送，从而盖过 `ANTHROPIC_AUTH_TOKEN` 中的 EZAT Router key。

**解决方法**：按上面的方法检查长度和前缀。取消设置工具同时会读取的其他服务商的 key（`unset ANTHROPIC_API_KEY`），或者也把它设为你的 EZAT Router key。如果 key 仍然无效，在 **API Key** 页面创建一个新的。

### 401 key 已吊销或已过期

消息为 `This API key has been revoked` 或 `This API key has expired`。

**原因**：有人吊销了这个 key，或者它已超过创建时选择的有效期。

**解决方法**：在 **API Key** 页面创建一个新 key，并更新工具的配置。key 无法重新启用。

### 403 权限错误

**原因**：以下情况之一：

- `This API key is not allowed to use …`：这个 key 创建时选择了**仅限选中的模型**，而这个模型不在其中。
- `This organization is suspended. Contact support@ezat.io.`：该组织的 key 全部会被拒绝。

**解决方法**：第一种情况，使用这个 key 允许的模型（用这个 key 调用 `GET /v1/models` 可以列出它们），或者创建一个可以使用所有模型的 key。第二种情况，发邮件到 support@ezat.io。

## 余额和限制

### 402 余额不足

消息为 `Your credit balance is too low. Add credits in the EZAT Router dashboard.` OpenAI 格式中的错误类型为 `insufficient_quota`。

**原因**：组织余额为零或负数。在余额大于零之前，请求都会被拒绝。

**解决方法**：在**账单**页面充值（所有者、管理员和财务可以充值）。付款几秒钟后额度就会到账。如果充值后仍然收到 `402`，检查你是否充到了 key 所属的组织：顶栏的组织切换器会显示你当前查看的是哪个组织。见[计费方式](https://docs.router.ezat.io/zh/billing.md)。

### 402 达到消费上限

消息为 `This API key reached its daily spend limit of …`（或 `monthly`、`total`）。

**原因**：这个 key 设置了消费上限，并且在当前周期内的花费已经达到上限。

**解决方法**：按天或按月的上限会在下一个 UTC 日或 UTC 月开始时重置。否则，换用上限更高的 key，或者创建一个。见[消费上限](https://docs.router.ezat.io/zh/api-keys.md)。

### 429 速率限制

错误类型为 `rate_limit_error`，并带有以秒为单位的 `retry-after` 响应头。消息会说明是哪种限制：

- `This API key exceeded its requests-per-minute limit`（`retry-after: 30`）：这个 key 每分钟发出的请求数超过了限制。
- `Rate limited upstream. Please retry shortly.`（`retry-after: 10`）：该模型的容量此刻正被限流。

**解决方法**：等待 `retry-after` 中的秒数，然后按退避策略重试。Anthropic 和 OpenAI 的 SDK 会自动重试这类错误。如果是你自己的流量触发了单个 key 的限制，请把请求分散到更长的时间里。见[速率限制](https://docs.router.ezat.io/zh/reference/rate-limits.md)。

### 529 过载（OpenAI 格式中为 503）

错误类型为 `overloaded_error`（OpenAI 格式中为 `server_error`，code 为 `overloaded`），并带有 `retry-after` 响应头。消息中可能会说该模型 `has no available capacity right now`。

**原因**：该模型此刻没有空闲的容量。返回这个错误之前，EZAT Router 已经尝试过它为该模型准备的其他容量。

**解决方法**：等待 `retry-after` 秒后，按退避策略重试。如果持续出现，换一个模型试试。

## 模型和请求

### 404 未知模型

Anthropic 格式中为 `not_found_error`，消息为 `model: <the name you sent>`。OpenAI 格式中 code 为 `model_not_found`。

**原因**：这个名称不是 EZAT Router 为这个 key 提供的模型 id 或别名。常见原因：拼写错误；使用了其他服务商的名称，或者云服务商自己的 id；模型已经下线；模型处于预览阶段，只有拥有预览权限的 key 才能调用。

**解决方法**：用 `GET https://api.router.ezat.io/v1/models` 列出你的 key 可以使用的模型，并发送其中一个 id。[模型](https://docs.router.ezat.io/zh/models.md)页面列出了每个模型可接受的其他名称。名称不区分大小写。在 Claude Code 中，如果你选择的模型没有提供，把 `ANTHROPIC_MODEL` 设为列表中的一个 id。

### 模型返回 400

错误类型为 `invalid_request_error`，消息中会指出某个字段或值。

**原因**：请求中有模型不接受的内容。EZAT Router 只检查 `model`、`max_tokens` 和 `messages`，其他内容按你发送的原样传给模型，所以适用的是模型自己的校验：例如模型不支持的采样参数（`temperature`、`top_p`、`top_k`），或者模型不提供的 `anthropic-beta` 功能。Message Batches、Files API、由 Anthropic 运行的服务端工具（网页搜索、代码执行）和 MCP connector 都不可用。

**解决方法**：去掉消息中指出的字段。如果 Claude Code 收到提示未知字段或 beta 功能的 `400` 错误，在它的环境中设置 `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS=1`。在兼容 OpenAI 的 API 上，少数 OpenAI 字段会被有意拒绝（例如大于 1 的 `n`、`logprobs`、`logit_bias`、音频和旧版的 `functions`）：见 [Chat Completions](https://docs.router.ezat.io/zh/openai/chat-completions.md)。

### 413 请求过大

错误类型为 `request_too_large`。

**原因**：请求体超过 32 MB。

**解决方法**：发送更小的图片或文档，或者减少每个请求中的图片或文档数量。

## 工具和设置

### 工具仍在使用自己的 key 或 base URL

症状：请求没有出现在**用量**页面上，工具报出的是其他服务商的错误，或者 key 明明正确却收到 `401`。

**原因**：工具从某个优先级更高的地方读取设置，覆盖了你设置的值：

- **Claude Code** 优先使用其设置文件中的 `env` 块，而不是你在 shell 中 export 的变量。已保存的 claude.ai 登录，或者你没有批准的 `ANTHROPIC_API_KEY`，也可能在起作用。
- **SDK 代码**如果在构造函数中传入了 base URL 或 key，就会忽略环境变量（`ANTHROPIC_BASE_URL`、`ANTHROPIC_API_KEY`、`OPENAI_BASE_URL`、`OPENAI_API_KEY`）。
- **不是从终端启动的应用**（编辑器、桌面应用）读不到你在 shell 中 export 的变量。
- **同时发送了两个 key**：见 [401 无效的 API key](#401-无效的-api-key)。

**解决方法**：

- 在 Claude Code 中运行 `/status`。`Anthropic base URL` 一行应该显示 `https://api.router.ezat.io`，`Auth token` 或 `API key` 一行应该指向保存你的 EZAT Router key 的那个变量。如果没有 base URL 这一行，说明变量没有传到 Claude Code。检查 `~/.claude/settings.json`、项目的 `.claude/settings.json` 和 `.claude/settings.local.json` 中是否有覆盖你设置的 `env` 值。如果 Claude Code 提示存在两个凭据，运行 `/logout` 清除已保存的登录。见 [Claude Code](https://docs.router.ezat.io/zh/tools/claude-code.md)。
- 在你的代码中，要么显式传入 `base_url` 和 key，要么去掉显式传入的值，让环境变量生效。
- 对于编辑器和桌面应用，在应用自己的设置中填写这些值。

### 流式输出提前中断

**原因**：以下情况之一：

- **模型在流式输出中途失败**。输出开始后，EZAT Router 无法再切换到其他容量，所以流会以一个错误事件结束：Anthropic 格式中是 `event: error`，OpenAI 格式中是带有 `error` 对象的 `data:` 块。这样失败的请求不收费。
- **你的客户端或代理关闭了连接**。EZAT Router 会停止模型。你需要为输入和截至当时已生成的输出付费；如果流在最终计数之前就结束了，输出量是估算的：**用量**页面会把这类请求标记为估算值，状态为**已取消**。
- **客户端的读取超时**短于事件之间的间隔。如果 15 秒内没有输出，EZAT Router 会发送一个保活消息（Anthropic 格式中是 `event: ping`，OpenAI 格式中是一条 SSE 注释）。

**解决方法**：以错误事件结束的请求，重试即可。确保客户端的读取超时远大于 15 秒，并且没有代理缓冲或切断长响应。

### 长请求返回 504

错误类型为 `timeout_error`，消息为 `The model took longer than 590 seconds. Send long requests with "stream": true.`

**原因**：不使用流式输出的请求，在模型完成之前收不到任何响应，EZAT Router 会在 590 秒后结束它。

**解决方法**：长请求请使用 `"stream": true` 发送（或者使用 SDK 的流式调用）。

## 联系支持

如果你无法自行解决问题，请发邮件到 support@ezat.io，并提供：

- 响应的 `request-id` 响应头；如果没有 `request-id`，提供 `x-request-id` 响应头（Anthropic 格式的错误响应体中，`request_id` 带有相同的值）；
- 请求的时间（含时区）、端点、状态码和错误消息；
- 如果是计费问题，提供**设置**中的**组织 ID**。

不要发送你的 API key：支持团队从不需要它。

## 给 AI agent 的说明

1. 在做任何修改之前，先读取状态码和错误 `type`。不要重试 `400`、`401`、`402`、`403`、`404` 或 `413`。
2. 对于 `429`、`500` 和 `529`（OpenAI 格式中为 `503`），至少等待 `retry-after` 秒，然后按退避策略重试。
3. 带有 `statusCode` 字段的 `404` 表示 URL 路径错误：Anthropic 格式的客户端用 `https://api.router.ezat.io`，OpenAI 格式的客户端用 `https://api.router.ezat.io/openai/v1`。
4. 检查 key 时，只打印它的长度和前 8 个字符，然后调用 `GET https://api.router.ezat.io/v1/models`。
5. 向用户求助时，给他们 `request-id`（或 `x-request-id`）和错误消息，绝不要给 key。