# 错误

## 信封

每个失败的调用都返回结构相同的 JSON 响应体，以及对应的 HTTP 状态码。

```json
{
  "error": {
    "code": "model_busy",
    "message": "model sam3 is busy; retry shortly",
    "retryable": true,
    "retryAfterMs": 5000
  }
}
```

| 字段 | 含义 |
|---|---|
| `code` | 稳定的、机器可读的错误码。应依据 `code` 而不是 `message` 判断。 |
| `message` | 面向人的说明，措辞可能变化。 |
| `retryable` | 为 `true` 时，原样重复请求有可能成功。 |
| `retryAfterMs` | 建议等待的毫秒数。无建议时为 0。 |

`429` 和 `503` 响应还带有 `Retry-After` 响应头，单位为整秒。

失败的调用不收费。返回错误的调用不会产生任何扣费。

## 错误码

| 状态码 | 错误码 | 可重试 | 含义 |
|---|---|---|---|
| 400 | `invalid_request` | 否 | 请求格式错误、字段超出范围，或图片未通过上传检查。 |
| 400 | `invalid_image` | 否 | 图片通过了上传检查，但无法解码。同一句柄之后始终返回该错误码。 |
| 400 | `unsupported` | 否 | 请求有效，但使用了尚未提供的功能，例如 `image.url`。 |
| 401 | `unauthorized` | 否 | API 密钥缺失、格式错误、无效、已过期或已吊销。 |
| 402 | `insufficient_balance` | 否 | 余额不足以支付本次调用的价格。 |
| 403 | `model_locked` | 否 | 密钥的范围或账户所在的模型池不允许使用该模型。 |
| 403 | `email_unverified` | 否 | 密钥所有者尚未验证邮箱。 |
| 404 | `not_found` | 否 | 路径不存在。 |
| 404 | `image_not_found` | 否 | `img_` 句柄未知、已过期或已被淘汰。应重新上传图片。 |
| 409 | `idempotency_conflict` | 否 | `Idempotency-Key` 已用于另一个不同的请求体。 |
| 409 | `request_in_progress` | 否 | 使用该 `Idempotency-Key` 的第一个请求仍在运行。 |
| 413 | `payload_too_large` | 否 | 请求体或图片超过大小限制。 |
| 429 | `rate_limited` | 是 | 达到模型池的每分钟限制（已储值账户：仅当余额无法支付该调用时）。 |
| 429 | `daily_limit_reached` | 否 | 公共池的每日额度已用完。 |
| 500 | `internal_error` | 否 | 意外的服务器错误。 |
| 502 | `upstream_error` | 是 | 调用在处理阶段失败。 |
| 502 | `bad_model_output` | 否 | 模型返回了无法使用的结果。 |
| 503 | `model_unavailable` | 是 | 当前没有 GPU 节点提供该模型。唯一的节点短时失联（约一分钟内）时，只有交互式调用得到该错误，带 `Retry-After: 5`；同步和批量调用在队列中等待，直到各自的截止时间。 |
| 503 | `model_busy` | 是 | 模型队列已满，或预计等待时间过长。 |
| 503 | `unavailable` | 是 | 临时性资源紧张，例如图片处理繁忙或图片存储不可用时。 |
| 504 | `upstream_timeout` | 是 | 调用超过了截止时间。 |

导致 `400 invalid_request` 的约束按字段列于 [API 参考](https://stack.foldbun.com/zh/docs/api/)。

`daily_limit_reached` 带有指向下一个 UTC 日的 `Retry-After`，但在此之前重复同一请求仍会失败。增加额度可获得更高限制。详见[速率限制与模型池](https://stack.foldbun.com/zh/docs/rate-limits/)。

## 重试建议

- 仅当 `retryable` 为 `true` 时才重复调用。
- 下一次尝试前，至少等待 `retryAfterMs`（或 `Retry-After` 秒数）。`model_unavailable` 和 `model_busy` 没有提示时，服务器建议等待 5000 ms。
- 对会消耗额度的调用发送 `Idempotency-Key`，使重复的调用不会被重复扣费或重复运行。
- 遇到 `404 image_not_found` 时，重新上传图片，然后即可重复调用。
- 其他 4xx 错误须先修改请求或账户，再进行下一次尝试。

## 请求 ID

每个响应（包括错误响应）都带有 `X-Request-Id` 响应头：由服务器生成的 16 个随机十六进制字符。客户端发送的值会被忽略。成功的推理响应还在 `id` 字段中带有调用 ID（`call_<uuid>`）。联系支持时应提供其中任一值。

## 幂等性

对任何会消耗额度的 `POST` 请求，发送 `Idempotency-Key: <1 至 128 个可打印 ASCII 字符>`。

- 在同一账户内，密钥保留 24 小时。
- 使用相同密钥和相同请求体重复请求，会返回原始响应（状态码和响应体），并带有响应头 `Idempotent-Replayed: true`。该调用不会再次扣费，也不会再次运行。
- 相同密钥搭配不同请求体，返回 `409 idempotency_conflict`。
- 第一个请求仍在运行时使用相同密钥，返回 `409 request_in_progress`。
- 只保存最终结果：`2xx` 和永久性的 `4xx`。`402`、`429` 或 `5xx` 会释放该密钥，因此可以用同一密钥重试相同的请求。

```bash
curl https://api.stack.foldbun.com/v1/ocr \
  -H "Authorization: Bearer $FOLDBUN_API_KEY" \
  -H "Idempotency-Key: 6d1a8b3e-1f6e-4f0c-9d54-2b8f7c1e0a11" \
  -H "Content-Type: application/json" \
  -d '{"image": {"id": "img_2dedd0716bfd46ec29b286a279d18b6fc80631e5d90fedb5c63eb36f231622e6"}}'
```
