# 错误

URL: https://docs.router.ezat.io/zh/reference/errors

> 网关以 Anthropic 和 OpenAI 格式返回的所有 HTTP 状态码和错误类型、各自的原因以及是否应该重试、流式输出中的错误，以及联系支持时需要提供的请求 id。

## 何时阅读本页

请求失败了，你想知道原因、是否应该重试，或者联系支持时要提供什么。各项限制和退避策略见[速率限制](https://docs.router.ezat.io/zh/reference/rate-limits.md)。

## 错误格式

错误使用你所调用的 API 的格式，两种格式下的 HTTP 状态码相同。

`/v1/*`（Anthropic 格式）：

```json
{
  "type": "error",
  "error": {
    "type": "not_found_error",
    "message": "model: anthropic/no-such-model"
  },
  "request_id": "0b1c6f2e-5d4a-4f7e-9a51-3f0e8d2c7b19"
}
```

`/openai/v1/*`（OpenAI 格式）：

```json
{
  "error": {
    "message": "The model `anthropic/no-such-model` does not exist or you do not have access to it.",
    "type": "invalid_request_error",
    "param": "model",
    "code": "model_not_found"
  }
}
```

Anthropic 和 OpenAI SDK 会把这些错误转换成各自的错误类（例如 `NotFoundError`），所以你很少需要自己解析。错误处理示例见 [curl](https://docs.router.ezat.io/zh/examples/curl.md)、[Node.js](https://docs.router.ezat.io/zh/examples/node.md) 或 [Python](https://docs.router.ezat.io/zh/examples/python.md)。

## 状态码

| 状态码 | Anthropic `type` | OpenAI `type` / `code` | 原因 | 是否重试 |
| --- | --- | --- | --- | --- |
| 400 | `invalid_request_error` | `invalid_request_error` / `null` | 请求体不是有效的 JSON，必填字段缺失或有误（`model`、`max_tokens`、`messages`），模型拒绝了某个参数，或兼容 OpenAI 的 API 不支持你发送的某个字段 | 否。修正请求。 |
| 401 | `authentication_error` | `invalid_request_error` / `invalid_api_key` | key 缺失、错误、已吊销或已过期 | 否。检查 key。 |
| 402 | `billing_error` | `insufficient_quota` / `insufficient_quota` | 组织余额为零或负数，或 key 已达到消费上限 | 否。充值或提高上限。 |
| 403 | `permission_error` | `permission_error` / `null` | 这个 key 无权使用该模型，或组织已被暂停 | 否 |
| 404 | `not_found_error` | `invalid_request_error` / `model_not_found` | 模型未知、已下线，或处于预览阶段而 key 没有预览权限 | 否。使用[模型](https://docs.router.ezat.io/zh/models.md)中列出的模型。 |
| 413 | `request_too_large` | `invalid_request_error` / `request_too_large` | 请求体超过 32 MB | 否。减少发送的内容。 |
| 429 | `rate_limit_error` | `rate_limit_error` / `rate_limit_exceeded` | key 超出了每分钟请求数限制，或提供方正在对该模型限流 | 是，等待 `retry-after` 之后 |
| 500 | `api_error` | `server_error` / `null` | 网关或提供方出现意外错误 | 是，带退避重试几次 |
| 504 | `timeout_error` | `server_error` / `timeout` | 非流式请求耗时超过 590 秒 | 加上 `"stream": true` 重新发送 |
| 529 | `overloaded_error` | 503, `server_error` / `overloaded` | 该模型目前没有可用容量，或网关尝试过的所有提供方都失败了 | 是，等待 `retry-after` 之后 |

在 Anthropic 格式返回 529 的情况下，兼容 OpenAI 的 API 返回 503，因为 OpenAI 客户端不认识 529。它针对模型返回的 404 还会设置 `"param": "model"`。

这些错误都不计费。见[计费方式](https://docs.router.ezat.io/zh/billing.md)。

### 可能看到的消息

| 状态码 | `message` |
| --- | --- |
| 400 | `Request body is not valid JSON`，或 `<field>: <problem>`，例如 `max_tokens: …` 或 `n: only 1 choice per request is supported` |
| 401 | `Missing API key. Send it in the x-api-key or Authorization: Bearer header.` |
| 401 | `Invalid API key`、`This API key has been revoked`、`This API key has expired` |
| 402 | `Your credit balance is too low. Add credits in the EZAT Router dashboard.` |
| 402 | `This API key reached its daily spend limit of …`（或 `monthly`、`total`） |
| 403 | `This API key is not allowed to use …` |
| 403 | `This organization is suspended. Contact support@ezat.io.` |
| 404 | `model: <the name you sent>` |
| 429 | `This API key exceeded its requests-per-minute limit`（`retry-after: 30`） |
| 429 | `Rate limited upstream. Please retry shortly.`（`retry-after: 10`） |
| 504 | `The model took longer than 590 seconds. Send long requests with "stream": true.` |
| 529 | `Overloaded`，或 `… has no available capacity right now`（`retry-after: 5`） |

由模型本身返回的 400（例如模型不接受某个参数）带有模型自己的消息。

### 不存在的路径

网关不提供的路径，例如 `/v1/messages/batches` 或 `/v1/files`，会返回简单格式的 404，不使用上面任何一种错误格式：

```json
{ "statusCode": 404, "message": "Cannot POST /v1/messages/batches" }
```

## 流式输出中的错误

流式响应一旦开始，HTTP 状态码就已经是 200。如果之后出错，网关会发送一个错误事件，然后结束流。这个请求在用量中标记为 **失败**，且不计费。

Anthropic 格式：一个 `error` 事件，之后没有 `message_stop`。

```text
event: error
data: {"type":"error","error":{"type":"api_error","message":"Upstream provider error"}}
```

OpenAI 格式：一个带 `error` 对象的 chunk，然后是 `[DONE]`。

```text
data: {"error":{"message":"Upstream provider error","type":"server_error","param":null,"code":null}}

data: [DONE]
```

错误类型与上表相同。Anthropic 和 OpenAI SDK 读到它时会抛出 `APIError`（或其子类），且不会重试：如果需要，请自己重新发送请求。

如果客户端在流式输出中途断开连接，不会有错误事件；见[中断的流式输出](https://docs.router.ezat.io/zh/billing.md)。

## 请求 id

有两个响应头用于标识请求：

| 响应头 | 出现在 | 值 |
| --- | --- | --- |
| `request-id` | 通过网关检查并到达模型的 messages 和 chat completions 请求，无论成功与否、是否流式 | 这个请求在用量中的 id |
| `x-request-id` | 每个响应，包括被拒绝的请求 | 本次 HTTP 调用的 id。如果你自己发送了 `x-request-id`（字母、数字、`.`、`_`、`:`、`-`，最多 128 个字符），网关会使用它并原样返回。 |

- 在 Anthropic 格式中，错误体里的 `request_id` 就是 `x-request-id`。
- 在兼容 OpenAI 的 API 上，completion 的 `id` 是 `chatcmpl-` 加上它的 `request-id`。
- Anthropic SDK 提供 `request-id`（`message._request_id`，以及 Python 中的 `error.request_id` 或 Node 中的 `error.requestID`）。被拒绝的请求没有 `request-id`，所以要从错误的响应头中读取 `x-request-id`。
- OpenAI SDK 提供 `x-request-id`（`completion._request_id`，Python 中的 `error.request_id`，Node 中的 `error.requestID`）。

## 联系支持

发邮件至 support@ezat.io，并附上：

1. `request-id`（如果响应中有）和 `x-request-id`。
2. 请求的时间（注明时区）、模型，以及你调用的是哪个 API（`/v1/messages` 或 `/openai/v1/chat/completions`）。
3. HTTP 状态码和错误的 `message`。

切勿发送你的 API key。请求和响应的内容不会被保存，所以请附上请求中相关的部分。

## 给 AI agent 的说明

1. 先看 HTTP 状态码，再看 `error.type`（Anthropic 格式）或 `error.code`（OpenAI 格式）。
2. 不要重试 400、401、402、403、404 或 413。修正请求，告诉用户检查 key 或在 https://router.ezat.io/zh/billing 充值，或者从 `GET https://api.router.ezat.io/v1/models` 中选择模型。
3. 对 429、500、529 和 503 使用指数退避重试；有 `retry-after` 响应头时，至少等待它给出的秒数。官方 Anthropic 和 OpenAI SDK 已经这样做了，默认重试两次。
4. 对于 504 `timeout_error`，加上 `"stream": true` 重新发送，而不是原样重试。
5. 在返回 200 之后，流仍可能以一个 `error` 事件（Anthropic）或 `error` chunk（OpenAI）结束。按 500 处理。
6. 报告问题时，把 `request-id` 和 `x-request-id` 响应头以及请求时间提供给用户。切勿包含 API key。