处理错误、限流和未知结果
分清可重试读取、可幂等恢复写入和需要用户修正的请求。
先识别失败发生在哪一步
连接建立、HTTP 拒绝、任务业务失败和输出下载失败有不同恢复方式。保存安全的 requestId、状态码和机器错误码用于排查;不记录 Key、用户完整输入和带身份信息的 URL。
| 现象 | 应做什么 | 不应做什么 |
|---|---|---|
| 400 / 422 | 按字段错误修正模式、素材或规格 | 原样高速重试 |
| 401 | 检查 Key 完整性、失效或到期 | 在日志打印密钥确认 |
| 402 | 检查额度与当前价格准入 | 更换用户身份规避计费 |
| 403 | 检查服务范围、冻结和权限 | 自动扩大 scope |
| 404 | 核对原模型、任务或素材 ID | 新建任务“找回”旧结果 |
| 409 | 区分幂等冲突、处理中与资源冲突,查询原状态 | 用同键发送不同正文 |
| 429 | 遵守 Retry-After,限制并发并退避;ACCOUNT_CONCURRENCY_LIMITED 表示账号同时进行的同步请求已满,等已有请求完成再发 | 用多个 Key 绕过限制(同一账号的 Key 共用额度) |
| 503 / 504 | 判断请求是否已经受理;有任务 ID 就继续查询原任务 | 无条件换键重提 |
| 查询返回 failed | 停止轮询,读取业务错误;明确发起新动作才重试生成 | 把 HTTP 200 当作生成成功 |
| SSE 提前断开 | 标记部分内容、保留用户输入 | 把截断内容作为完整结果 |
OpenAI SDK 错误对象
公开模型接口返回非 2xx 时,官方 OpenAI SDK 会抛出异常。平台同时返回旧客户端可读的顶层字段和标准兼容的嵌套 error:
{
"error": {
"message": "max_tokens maximum is 4096",
"type": "invalid_request_error",
"param": "max_tokens",
"code": "invalid_argument",
"requestId": "req_example",
"retryable": false,
"details": {"limit": 4096}
},
"code": "invalid_argument",
"message": "max_tokens maximum is 4096",
"requestId": "req_example",
"retryable": false
}Python SDK 常用字段是 APIStatusError.status_code、code、param、request_id 和 body;Node/TypeScript SDK 常用字段是 APIError.status、code、param、requestID 和 error。完整正文在 body/error 中,details 用于限制值等机器信息。应用应保存状态码、错误码和请求 ID,不要依赖自然语言正文解析。
retryable=true 才表示平台允许按该错误的恢复语义重试;429 还应遵守 Retry-After。请求已经发往模型但结果未知时,即使是 5xx 也不能盲目重放;若接口支持幂等,应使用同一身份、同一业务键和同一正文查询或恢复。
流式响应如果已经产生部分内容后发生断流,SDK 会收到流错误;部分文本必须标记为不完整,不得当作成功结果或补写伪造的 [DONE]。
写入结果未知
响应丢失不等于服务端没有执行。公开操作声明支持幂等时,用同身份、同业务键、同正文恢复;已经取得 ID 时优先查询。未声明幂等的操作不自动重放。
API Key 创建不提供秘密找回,遵循 创建结果不确定。一次性会话交换与模型生成不是同一种重试协议。
计费与等待
请求可能先进行额度预占,再按最终执行事实结算。页面报价不是永久锁定价格;最终由真实请求命中的规则决定。上传成功、任务受理和模型完成是三个不同事实。
缩短客户端超时不会加速执行,也不会自动取消已受理任务。为每条链设置总等待预算和最大退避时间;不要对网络问题无限轮询。