AI API 报错怎么办?400、401、429、超时与流式中断排障指南
按请求链路定位 AI API 常见错误,区分限流与额度问题,建立超时、有限重试、日志脱敏和流式中断处理的实用方案。

AI API 出错时,连续点击“重试”很容易让问题变得更复杂:凭证错误不会被重试修复,限流可能被更多请求放大,而超时后的再次发送可能生成第二份结果。
有效的排障顺序是先确定请求在哪一层失败,再判断原因是否暂时,最后决定是否重试。本文面向 HTTP AI API,使用兼容 Chat Completions 的文本请求说明方法;具体错误字段和限制规则以服务商文档为准。
一、先收集一份最小证据
出现错误时,先记录发生时间和时区、目标主机与路径、模型 ID、HTTP 状态码、脱敏后的错误类型、请求耗时以及请求 ID(如果服务提供)。不要记录完整 Authorization 请求头。
把请求体缩减为一句普通文本,暂时移除历史对话、工具定义、图片和非必要参数。如果最小请求成功,就逐项恢复原请求;如果仍然失败,优先检查地址、权限和链路。
下面是一份适合工单的记录模板:
发生时间:2026-10-12 14:30,UTC+08:00
接口:POST /v1/chat/completions
模型:填写实际模型 ID
状态:429
错误类型:填写脱敏后的 type/code
耗时:填写本次测量值
请求 ID:有则填写,没有则注明未返回
是否最小请求也失败:是 / 否
最近变更:模型、参数、网络或依赖是否改变
这些值是记录格式示例,不是某个平台的故障数据。分享时还要检查主机信息、输入片段和错误内容是否涉及内部业务。
二、按状态码缩小范围
| 现象 | 优先检查 | 通常应采取的动作 |
|---|---|---|
| 400 或 422 | 请求字段、类型、上下文和模型参数 | 修改请求,再测试 |
| 401 | 密钥是否有效、认证格式是否正确 | 修复凭证或认证配置 |
| 403 | 账户或资源权限、访问规则 | 确认权限与服务规则 |
| 404 | URL 路径、模型或资源是否存在 | 检查路径和资源标识 |
| 429 | 限流、额度或用量限制 | 先识别错误原因,再决定处理 |
| 500、502、503、504 | 服务链路或网关异常 | 结合业务允许有限重试 |
| 无 HTTP 状态码 | DNS、TLS、代理、连接和超时 | 从网络层定位 |
这是排查入口,而不是所有服务通用的错误语义。相同状态码可能对应不同原因,服务商也可能返回自定义状态。OpenAI 官方的 错误码说明可作为直连接口的参考,不能据此推断第三方所有错误含义。
400:先减参数,别先换网络
常见问题包括 messages 格式错误、字段类型不对、模型不支持某个参数,或者上下文过长。恢复到 model 加一条 user 消息的最小请求,确认成功后逐个增加字段。若加入某个参数后立即失败,查看该模型的支持范围。
401 和 403:认证与权限分开看
401 排查密钥是否进入当前进程、是否复制了多余空格,以及请求头是否为服务要求的认证格式。403 则应进一步看模型权限、账户策略和访问规则。不要将更换 IP 或更换密钥当作没有依据的默认操作。
404:看完整路径,也看错误体
/v1/v1/chat/completions 是典型的路径重复。另一种情况是路径正确,但模型 ID 不存在或资源不可访问。错误体如果返回 HTML,也可能来自网页服务器或网关,而不是模型 API。
三、429 为什么不能统一重试?
429 可能是请求频率或 token 用量超过当前限额,也可能与额度、支出或其他账户限制有关。前者通常需要降低速率并等待;后者需要处理账户状态,反复重发不能解决。
不要只判断错误描述中有没有英文单词 quota。优先使用文档定义的 type 或 code,并检查账户信息。无法分类时停止自动重试,把脱敏信息交给维护人员确认。
对于明确可重试的限流,优先遵循 Retry-After,然后结合指数退避和随机抖动。该头可能是等待秒数,也可能是 HTTP 日期。服务没有提供该头时,再使用本地等待策略。OpenAI 的 限流指南说明了速率控制与退避的基本思路。
退避只能缓解短暂问题。如果每次任务都会触发限流,应减少并发、缩小输出预算或排队执行,而不是不断提高重试次数。
四、超时不等于服务端没有执行
连接超时、读取超时和整个任务的截止时间是不同概念。客户端没有按时收到结果,并不能证明上游没有开始或完成生成。
因此,给纯文本生成增加重试时也要考虑额外用量;给图片生成、文件处理或带工具执行的任务增加重试时,更要考虑重复结果和副作用。除非服务明确提供并保证相应幂等机制,否则不能把自定义请求 ID 当作防止重复执行的凭证。
应用可以生成自己的任务 ID,用于关联日志和阻止重复点击。它只能帮助控制应用侧行为,不能自动取消已经发送到上游的任务。
五、一个有限重试的 Python 模板
下面示例使用 requests,只演示非流式、无工具副作用的文本生成。需要 Python 3.10 或更新版本,安装依赖并配置 AI_BASE_URL、AI_API_KEY、AI_MODEL。
python -m pip install requests
代码默认不自动重试 429,因为兼容服务的错误码无法统一判断;确认服务文档后,可把明确的瞬时限流 code 添加到集合中。对可重试的 HTTP 错误最多发送三次。连接与读取异常直接抛出,让调用者决定是否恢复。
import os
import random
import time
from datetime import datetime, timezone
from email.utils import parsedate_to_datetime
import requests
# 仅填写服务文档明确说明可以等待重试的 code。
RETRYABLE_429_CODES = set()
RETRYABLE_STATUS = {500, 502, 503, 504}
MAX_ATTEMPTS = 3
MAX_INLINE_WAIT = 30.0
def retry_after_seconds(value):
if not value:
return None
try:
return max(0.0, float(value))
except ValueError:
try:
target = parsedate_to_datetime(value)
if target.tzinfo is None:
target = target.replace(tzinfo=timezone.utc)
return max(0.0, (target - datetime.now(timezone.utc)).total_seconds())
except (ValueError, TypeError, OverflowError):
return None
def get_error_code(response):
try:
body = response.json()
except ValueError:
return None
if not isinstance(body, dict):
return None
error = body.get("error")
return error.get("code") if isinstance(error, dict) else None
def generate_text():
url = os.environ["AI_BASE_URL"].rstrip("/") + "/chat/completions"
headers = {
"Authorization": "Bearer " + os.environ["AI_API_KEY"],
"Content-Type": "application/json",
}
payload = {
"model": os.environ["AI_MODEL"],
"messages": [{"role": "user", "content": "用一句话解释缓存。"}],
}
with requests.Session() as session:
for attempt in range(MAX_ATTEMPTS):
with session.post(
url, headers=headers, json=payload, timeout=(5, 30)
) as response:
if response.ok:
body = response.json()
return body["choices"][0]["message"]["content"]
code = get_error_code(response)
retryable = response.status_code in RETRYABLE_STATUS
if response.status_code == 429:
retryable = (
isinstance(code, str) and code in RETRYABLE_429_CODES
)
if not retryable or attempt == MAX_ATTEMPTS - 1:
response.raise_for_status()
delay = retry_after_seconds(response.headers.get("Retry-After"))
if delay is None:
delay = random.uniform(0.5, min(8.0, 2.0 ** (attempt + 1)))
if delay > MAX_INLINE_WAIT:
raise RuntimeError(
f"服务要求至少等待 {delay:.1f} 秒,请转为延迟任务"
)
time.sleep(delay)
raise RuntimeError("重试流程未取得结果")
if __name__ == "__main__":
print(generate_text())
timeout=(5, 30) 分别设置连接和读取等待,单位为秒。它不是严格的整项任务总时限;生产系统应在任务层增加截止时间或队列超时。服务要求的等待时间过长时,示例退出而不是把等待时间强行截短,这样不会提前重发。
这个模板还需要业务侧验证返回文本和输出格式。HTTP 成功只说明请求层成功,不保证模型完成了你的业务目标。
六、避免两层重试叠加
如果 SDK 自己重试,外层任务也重试,总发送次数会相乘。例如两层各允许最多三次尝试,最坏情况下可能产生九次发送。应明确由哪一层负责重试,并记录总尝试次数。
使用 OpenAI Python SDK 时,可以显式设置 max_retries=0,交给业务统一处理,或直接使用 SDK 的有限重试并关闭外层重复机制。具体行为应依据安装版本与 官方 SDK 文档确认。
七、流式输出断了,应该怎么办?
流式连接可能先返回成功状态,之后在读取事件时断开,因此只监控 HTTP 状态码会漏掉故障。
应用需要分别标记“收到首个片段”“流正常结束”和“读取中断”。如果用户已经看到半段回答,重试时应明确开始一次新生成,不能把新结果无提示地接在旧文本后。断线后的续传能力必须由服务协议提供,不能自行假定存在。
八、把稳定性变成可观察的行为
至少记录成功率、各类失败数量、每次尝试耗时、重试次数,以及流式请求的首片段等待与完整结束率。失败也要纳入统计,不能只统计成功请求然后得出“接口很快”的结论。
处理能力不足时,用有界队列和有限并发;服务连续异常时暂缓新请求并提示用户稍后再试。日志只保存排障必要的信息,敏感输入默认不记录,确需样本时再经过脱敏与权限控制。
下一次报错,可以按“最小请求 → 状态与错误类型 → 地址/权限/限流/链路 → 有限恢复”的顺序处理。目标是让每一次失败都能解释,而不是让重试隐藏问题。

