API 错误码
System One API 的错误结构、HTTP 状态码,以及在 TypeScript SDK 中的处理方式。
处理 HTTP API 与控制台端点的错误,或集成 System One SDK 时可使用本参考。Playground 显示面向用户的提示;应用应根据文档说明的响应头对错误分类。
常见问题
Q: System One API 如何处理错误?
A: 返回一致的错误包络与 HTTP 状态码;TypeScript SDK 以类型化错误抛出。重试前先处理错误,并在适当时使用幂等键。
需要保存的信息
保存 HTTP 状态、X-System-One-Error-Code、X-Request-Id 和请求时间。根据响应头中的错误码决定下一步,而不是匹配提示措辞,也不要假定所有错误正文结构相同。不要记录 API 密钥、认证头或敏感请求内容。
识别错误来源
结合 X-System-One-Error-Source 与 X-System-One-Error-Code 进行判断。upstream 表示有效的模型服务 JSON 错误保留原始 400–599 HTTP 状态和正文。正文可以是对象、数组、字符串、其他 JSON 标量或 null,不一定使用 System One 错误结构。例如:
{
"detail": [
{ "loc": ["body", "questions"], "msg": "Invalid question definition", "type": "value_error" }
]
}这只是格式示例,不是真实错误记录。稳定响应头将 HTTP 429/529 分类为 provider_busy,400/422 为 provider_rejected_request,其他上游 HTTP 失败为 provider_unavailable。上游 401/403 保持原状态,不代表调用者的 System One 登录已过期。即使来源为 platform,provider_* 错误也可能是经过安全替换的模型服务错误,而非账户认证问题。
Retry-After 可以是秒数或 HTTP 日期,安全可用时会保留。请根据稳定分类生成本地化提示,不要直接显示任意 message 或 detail 原文;错误正文可能回显敏感输入。X-Upstream-Request-Id 与 X-TypeSafe-Request-Id(若存在)是独立跟踪标识,不等同于 System One 的 X-Request-Id。
System One 错误结构
X-System-One-Error-Source: platform 标识 System One 错误或安全替换。其 JSON 结构包含 error.code;同时处理两种来源时优先读取响应头分类。支付端点有独立的支付契约。
典型的 System One 错误结构如下,值仅为示例:
{
"error": {
"code": "insufficient_credits",
"message": "This request requires 3 credits. Top up your account to continue.",
"request_id": "example-request-id"
},
"request_id": "example-request-id"
}其他错误正文可能不同。支持查询和费用核对使用的请求 ID 应从 X-Request-Id 读取,不要使用任意正文字段。provider_* 错误表示模型请求未能完成;即使 HTTP 状态为 401 或 403,也不代表你的 System One 密钥或浏览器登录已过期。
密钥与请求问题
| HTTP | 错误码 | 处理方式 |
|---|---|---|
| 400 | invalid_json | 发送有效的 UTF-8 JSON,不要使用重复对象键。 |
| 401 | invalid_api_key | 检查 Bearer 密钥;密钥已撤销或遗失时,在控制台创建新密钥。 |
| 401 | unauthorized | 此端点需要已认证账户或会话。请登录;Bearer 密钥不能代替控制台会话。 |
| 403 | account_disabled | 联系支持查询账户状态。 |
| 403 | invalid_origin | 会话修改请求缺少与应用一致的 Origin,或来自其他源。请从已登录的应用源操作。 |
| 404 | not_found | 检查主应用源和文档路径;控制台路径以 /api/system-one 开头,不是 /v1。 |
| 405 | method_not_allowed | 使用端点文档指定的方法:决策用 POST,列表用 GET,撤销密钥用 DELETE。 |
| 404 | key_not_found | 密钥 ID 未知或属于其他账户。请检查自己的密钥列表。 |
| 413 | request_too_large | 原始正文超出所选模型或端点限制:Jev/HTTP 模式为 65,536 字节,支持图片的 Clef 最高 13,631,488 字节(目录可收紧);创建密钥为 4,096 字节。 |
| 415 | unsupported_media_type | 发送 Content-Type: application/json。 |
| 422 | invalid_request | 检查提示字段和所选模型的限制。 |
| 422 | unsupported_model | 从模型列表复制当前模型 ID。 |
| 422 | invalid_idempotency_key | 遵守操作键格式。 |
认证和初始请求校验失败发生在新决策积分预扣前,不产生新决策费用。这包括不支持的模型和模型专属输入、扩展限制,请检查所选目录条目的限制。决策中的重复对象键无效,即使它们通过转义后才同名。超出受支持有限范围的数字、无效名称,以及不受支持的 null 或省略形式也可能校验失败。服务不会补造默认答案或自动换模型。一次失败不会撤销其他已发生的操作。
余额、限流与重复请求
| HTTP | 错误码 | 处理方式 |
|---|---|---|
| 402 | insufficient_credits | 检查余额;补充积分,或减少本次请求的问题数及大小。 |
| 409 | key_limit_exceeded | 此账户已有 20 个有效密钥,创建前请撤销不再使用的密钥。 |
| 409 | idempotency_conflict | 此键已用于不同请求。恢复原请求体以找回结果;确实需要新操作时,使用新键。 |
| 409 | request_in_progress | 按 Retry-After 等待,再用相同键和请求体重试。 |
| 409 | idempotency_failed | 原操作失败且积分已返还。只有明确决定重新尝试时才使用新键。 |
| 409 | request_expired | 原操作在完成前已结束并返还积分。再次提交前先查看记录。 |
| 410 | idempotency_expired | 原答案已无法重放。发起新操作前先核对原操作。 |
| 429 | rate_limit_exceeded | 按 Retry-After 等待。API 密钥和 Playground 共享账户决策限额。 |
重放保护从请求创建起持续 24 小时,并非永久有效。过期键可能直接开始新的计费操作,而不返回 410。详见幂等与重试。
决策尝试共享账户窗口(默认每分钟 120 次),覆盖各密钥、Playground 和重放。模型列表另有每账户每分钟 60 次限制;创建密钥另有每账户每分钟 10 次限制。API 认证还有每 IP 每分钟 600 次尝试的独立限制。本地 429 中的 X-RateLimit-Limit、X-RateLimit-Remaining 和 X-RateLimit-Reset 描述已耗尽的窗口,Retry-After 给出等待秒数。Reset 是 Unix 秒时间戳,不是时长。上游限额使用独立的 X-Upstream-RateLimit-* 命名空间。
服务问题
| HTTP | 错误码 | 处理方式 |
|---|---|---|
| 429 / 529 | provider_busy | 模型服务繁忙。遵守 Retry-After,再次尝试前查看已记录的结果。 |
| 400 / 422 | provider_rejected_request | 再次尝试前检查请求和所选模型的要求。 |
| 502 或其他 4xx / 5xx | provider_unavailable | 模型请求未能完成。核对结果,持续发生时联系支持。 |
| 502 | invalid_provider_response | 模型返回无效、不安全、非 JSON、无效 UTF-8、超过 1MB 的响应或重定向。不会生成默认决策。 |
| 504 | provider_timeout | 模型响应头和正文共用的 20 秒期限已到。请检查已记录的结果。 |
| 499 | request_cancelled | 请求已取消。提交新操作前先检查记录。 |
| 503 | provider_not_configured、provider_configuration_error、app_not_configured | 服务需要处理。请联系支持,不需要你修改服务设置。 |
| 503 | model_catalog_unavailable | 当前模型目录无法加载,未开始新的评估。稍后重试或联系支持,不要沿用记忆中的模型价格。 |
| 501 | model_listing_not_supported | 当前连接无法获取模型列表。请使用 Playground 模型选择器,并联系支持。 |
| 503 | request_reconciliation_pending | 请求费用尚未核对完成。保留 ID 并检查控制台用量,不要假定新尝试免费。 |
| 500 | internal_error | 保留请求 ID,再次尝试前先检查原操作。 |
重试前核对费用
通常,评估失败会返还本次尝试扣除的积分。X-System-One-Credits: 0 表示本次没有保留扣费。如果即时费用核对未能完成,服务会返回 request_reconciliation_pending,并省略此响应头。缺失费用头不等于零费用。 请查看积分与计费和控制台用量记录。
你使用的工具超时或断线,并不能证明操作失败。请用相同操作键和请求体恢复结果。确认失败且积分已返还后,新尝试才需要使用新键。避免自动换新键重试。
模型列表与密钥管理请求不预扣决策积分。普通评估失败会先确认返还积分,再返回错误。即时对账失败时,503 request_reconciliation_pending 优先于原错误返回,并省略费用头。不能把响应头缺失、客户端超时或连接取消当作已确认退款。
安全例外与响应头
含不安全凭据信息的错误正文会替换成安全的 System One 结构,同时保留 HTTP 状态和稳定的 provider 分类,来源改为 platform。不安全的成功响应会被拒绝,不会返回给调用者。格式错误的 JSON、无效 UTF-8、超限响应和重定向也会被拒绝,且不会跟随重定向。因此不能假定每个模型服务响应都按字节无条件透传。
仅转发文档列出的安全跟踪、限流头,以及 Content-Type 和 Retry-After。包含密钥的头值会被省略,不转发 Cookie、认证或 Location。System One 的 no-store、安全与 CORS 规则始终有效。可读取的头,以及 Bearer API 与同源会话端点的区别,见浏览器访问。
SDK 错误处理
System One 的 @system-one-ai/core@0.8.0 SDK 导出 APIError,包含 statusCode、requestId 和 retryAfterMs,但不暴露完整服务端错误正文或分类头。集成需要区分不同的 409 错误码时,请使用 Fetch。独立维护的官方 @typesafe-ai/sdk@0.6.0 有自己的错误类;不要假定两套客户端暴露相同结构,也不要直接记录整个错误对象。参阅 SDK 请求与客户端。
已发布的 core 0.8.0 保留相同的 APIError 接口;图片和抽取支持并未增加托管错误分类头的访问能力。图片格式、表示形式、数量、解码大小或所选模型能力不符合要求时,会在预扣前拒绝。有效图片请求在上游失败时仍遵循现有退款/对账规则。托管决策图片客户端使用 Fetch,需显式检查 response.ok 与响应头。Clairic 抽取错误使用相同的 APIError 字段。
客户端重试策略与服务行为独立,服务不会自动重试模型推理。响应不确定时,应使用保存的键和正文恢复。确认失败且已退款后,相同键会返回 idempotency_failed;只有明确决定重新尝试时才使用新键。参阅幂等与重试。
错误或费用问题未解决时,请向 support@system-one.dev 提供请求 ID、时间、状态和错误码。不要发送 API 密钥或敏感提交内容。