先保留状态、请求标识和响应体错误代码

很多 SDK 把各种失败包装成一个异常,但恢复动作不能只根据异常文案决定。最小故障记录应包含时间、接口和模型、HTTP 状态、服务方请求标识、响应体错误代码、是否收到完整响应,以及本次操作是否可能写入外部系统。不要记录密钥、完整提示词或个人信息。若根本没有 HTTP 响应,应标记为网络或客户端超时,不要臆造一个 500。

time: 2026-10-17T06:00:00Z
operation: create_report
http_status: 429
provider_error_code: rate_limit_exceeded
request_id: req_demo_42
retry_after: 30
side_effect: yes
result_confirmed: unknown

这份模板有意没有响应体原文:只保留足以追踪问题的字段。各供应商的错误码、请求标识头名称不同,请按实际接口映射。

案例一:429 和 30 秒等待

HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json

{"error":{"code":"rate_limit_exceeded"}}

429 表示请求速率受到限制;Retry-After: 30 表示服务方建议至少等待 30 秒后再请求。先检查同一账户的并发、队列长度和速率限制,再安排有上限的重试。如果一百个工作进程同时收到 429,全部在第 30 秒一起重试会形成新高峰,因此仍需控制共享队列并加入抖动。若响应没有 Retry-After,以供应商文档为准,采用有最大等待和总次数限制的退避策略。

在错误分诊工具中选择“429”,填入“30”,先查看只读操作的建议;再勾选“可能创建记录、发消息或扣费”。你会看到等待时间不变,但重试前多了确认业务结果与幂等机制的步骤。

案例二:写入操作超时

POST /reports
client_timeout: 10s
HTTP response: none
local_request_id: report_42

客户端十秒后断线,服务器可能还在处理,也可能已写入成功。先按业务标识查询 report_42 是否存在;若服务提供幂等键,则用同一个键核实或重试。若没有查询接口和幂等保证,应暂停自动重试并人工确认,避免生成两份报告。把这例选成“客户端超时 / 断线”并勾选副作用,就能得到相同的判断顺序。

案例三:400 参数错误

HTTP/1.1 400 Bad Request
Content-Type: application/json

{"error":{"code":"invalid_request","field":"max_output_tokens"}}

这里优先查该字段的类型、取值范围及模型是否支持它。用去掉业务数据的最小请求重现;与成功请求做结构差异对比。固定间隔重试相同的请求通常没有意义。若错误信息指向 JSON 语法,先用JSON 检查器确认请求体能解析;解析通过以后仍需核对字段契约。

一张可执行的处理表

观察先查什么能否立即重试
400 / 422请求字段、类型和限制先修正输入
401 / 403凭证、权限和目标项目先修正配置
429速率、并发、Retry-After等待并控制重试
5xx服务状态、请求标识、响应体只在安全边界内重试
无响应 / 超时网络阶段和业务结果写入操作先核实结果
这张表是分诊起点,不是供应商错误码全集。尤其是余额不足、配额耗尽和模型不可用等原因,可能使用服务方特定的状态或错误代码;最终以响应体和官方文档为准。

依据:RFC 6585:429、RFC 9110:Retry-After。本站的副作用处理建议是工程实践判断,不是 HTTP 规范对所有业务的保证。