参考
错误
所有非 2xx 响应共用同一个信封。HTTP 状态码 + error.type 一起告诉你该做什么——重试、退避、修请求,还是停止。
错误信封
所有错误响应都是同一形态的 JSON。最外层的 type 永远是字面量字符串 "error";真正有意义的是 error.type。
错误响应
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "max_tokens must be a positive integer."
}
}状态码
| HTTP | type | 出现时机 |
|---|---|---|
| 400 | invalid_request_error | 请求体格式错误或违反约束(未知模型、max_tokens 过大、messages 数组形态错)。不要重试——修请求。 |
| 401 | authentication_error | API 密钥缺失、格式错或无效。原样重试无用——请重新认证。 |
| 402 | insufficient_quota | 你的 apiCredits 余额不够本轮所需。硬停止。请在 /developers/billing 充值。 |
| 403 | permission_error | 密钥认证通过,但不允许访问该接口(CLI 密钥发到 /v1/*、账户被暂停、权限范围不匹配)。 |
| 404 | not_found_error | 路径或资源不存在。请检查 URL 和模型 id。 |
| 413 | request_too_large | 请求体超过 16 MB 上限。请拆分负载或下采样图片。 |
| 429 | rate_limit_error | 命中按密钥的速率限制。请遵守 Retry-After。不消耗积分。 |
| 500 | api_error | 我们这边的内部故障。请退避后重试。幂等。 |
| 502 | api_error | 上游供应商返回错误。请退避后重试。 |
| 503 | api_error | 服务暂时不可用(部署、维护)。请退避后重试。 |
| 504 | api_error | 供应商超时。请退避后重试。可考虑调小 max_tokens。 |
| 529 | overloaded_error | 上游模型容量受限。请退避后重试,通常几秒后恢复。 |
如何分类处理
- 可重试:429、500、502、503、504、529。使用带抖动的指数退避。存在
Retry-After就遵守。最多 4–6 次。 - 硬停止:402(
insufficient_quota)以及 401/403(authentication_error、permission_error)。重试都没用。请上报到人工或告警通道。 - 修请求:400(
invalid_request_error)和 413。下次发送前先校验;从调用方修复。
消息 ID
每个成功响应都带 id 字段(在 /v1/messages 上形如 msg_01H8fkx2N3p4q5r6s7t8u9v0wx,在 /v1/chat/completions 上形如 chatcmpl_...)。每次调用都把 id 保存下来。提工单时这个 id 是我们追溯请求完整生命周期最快的方式:选了哪家供应商、预留了多少、实际计费多少。
一个可复用的小处理器
用一个函数把每个调用点都包起来,按上面三类对响应分类。下面的示例区分 insufficient_quota(不要重试)、rate_limit_error(重试)和瞬时供应商错误(重试),由调用方决定重试策略。
# Inspect the type field to decide what to do.
status=$(curl -s -o /tmp/body -w "%{http_code}" \
-X POST https://caicaini.com/v1/messages \
-H "Authorization: Bearer cai_api_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"caicaini/auto","max_tokens":50,"messages":[{"role":"user","content":"Hi"}]}')
errtype=$(jq -r '.error.type // empty' /tmp/body 2>/dev/null)
echo "status=$status type=$errtype"
case "$status$errtype" in
200*) echo "ok" ;;
402*|*insufficient_quota) echo "top up at /developers/billing"; exit 2 ;;
429*|*rate_limit_error) echo "throttled — sleep, then retry" ;;
500*|502*|503*|504*|529*) echo "transient — retry with backoff" ;;
*) echo "fatal — fix the request"; exit 1 ;;
esac