调用 GPT、Claude、Gemini API 报错怎么办:一套通用排查清单
调用大模型 API 时,报错往往不在模型本身,而在认证、请求格式、网络、配额、模型名称或响应解析环节。
本文给出一套适用于 GPT、Claude、Gemini 以及其他兼容 HTTP API 的通用排查流程。能力、可用区域、上下文限制、价格和计费规则都会变化,下面涉及的参数和接口名称应以对应服务商当前文档为准。
一、先建立最小可复现请求
不要一开始就在完整业务系统中排查。先准备一个只包含以下内容的最小请求:
- API 地址
- 认证信息
- 模型名称
- 一条短文本
- 必要的请求头
- 完整的 HTTP 状态码和响应体
可以使用下面的 Python 脚本验证基础连通性。运行前设置API_URL、API_KEY和REQUEST_BODY环境变量。
importjsonimportosimportsysfromurllib.requestimportRequest,urlopenfromurllib.errorimportHTTPError,URLError api_url=os.environ.get("API_URL")api_key=os.environ.get("API_KEY")request_body=os.environ.get("REQUEST_BODY",'{"input":"请回复:ok"}')ifnotapi_urlornotapi_key:sys.exit("请先设置 API_URL 和 API_KEY")try:body=json.loads(request_body)exceptjson.JSONDecodeErrorasexc:sys.exit(f"REQUEST_BODY 不是合法 JSON:{exc}")request=Request(api_url,data=json.dumps(body).encode("utf-8"),headers={"Content-Type":"application/json","Authorization":f"Bearer{api_key}",},method="POST",)try:withurlopen(request,timeout=30)asresponse:result=response.read().decode("utf-8",errors="replace")print("HTTP",response.status)print(result)exceptHTTPErrorasexc:error_body=exc.read().decode("utf-8",errors="replace")print("HTTP",exc.code,file=sys.stderr)print(error_body,file=sys.stderr)exceptURLErrorasexc:sys.exit(f"网络错误:{exc.reason}")不同服务的认证头不一定相同。若服务商要求其他头部,应按文档调整,不要默认所有接口都使用Authorization: Bearer。
二、按错误类型定位
1. 没有收到 HTTP 响应
常见表现:
timeoutconnection refusedDNS resolution failedTLS/SSL error代理连接失败
排查顺序建议如下:
- 检查域名是否能解析。
- 检查当前网络是否允许访问目标域名和端口。
- 检查
HTTP_PROXY、HTTPS_PROXY、NO_PROXY等环境变量。 - 检查系统时间是否准确,证书校验依赖正确时间。
- 用
curl -v或等价工具观察 DNS、TLS 和重定向过程。 - 将客户端超时时间分成连接超时和读取超时,避免把两者混为一谈。
不要因为一次网络超时就立即判断服务不可用。应记录发生时间、地区、网络类型和请求耗时,再进行多次独立验证。
2.401或403:认证与权限
重点检查:
- API Key 是否为空、过期或被撤销。
- 是否把密钥放在了错误的请求头中。
- 请求是否误用了另一家服务的密钥。
- 项目、组织、区域或租户配置是否正确。
- 当前密钥是否有调用该模型或接口的权限。
- 服务端是否要求额外的版本头、项目头或区域参数。
不要把完整密钥打印到日志。排查时只显示前几位和后几位,并在确认泄露后立即撤销并重新生成。
3.400或422:请求格式错误
这类错误通常是参数结构问题,而不是网络问题。检查:
- JSON 是否有效,字符串引号是否闭合。
- 字段名称是否符合当前接口版本。
messages、contents、input等顶层结构是否使用正确。role、文本块、图片块的嵌套层级是否正确。- 数值字段是否传成了字符串。
- 是否同时发送了互相冲突的参数。
- 是否把某个接口的请求体直接复制到另一家服务。
建议把最终发送到网络层的 JSON 保存为脱敏样本,而不是只查看业务对象。很多 SDK 会在发送前修改字段,直接查看原始对象可能无法发现问题。
4.404:地址或模型标识错误
404可能表示:
- URL 路径拼写错误。
- API 版本路径不匹配。
- 区域或项目路径缺失。
- 模型名称不存在、已下线或当前账号不可见。
- 将聊天接口、生成接口和模型详情接口混用了。
模型 ID 不要写死在多个业务模块中。集中配置,并在启动时打印经过脱敏处理的接口地址和模型 ID,便于确认实际使用的配置。
5.429:频率、并发或配额问题
429不一定只代表“请求太快”,还可能与以下因素有关:
- 每分钟请求数或令牌数达到上限。
- 并发连接数超过限制。
- 账户余额、项目预算或月度额度不足。
- 输入过长导致令牌配额消耗过快。
处理方式:
- 优先读取响应中的
Retry-After。 - 对临时性限流使用指数退避和随机抖动。
- 限制客户端并发,并为队列设置上限。
- 对输入长度和输出长度进行预算。
- 将配额不足与瞬时限流分别记录,避免无意义重试。
不要通过共享账号、绕过账户控制或规避平台限流来解决问题,这会带来安全和合规风险。
6.500、502、503:服务端或网关错误
先确认请求本身在其他时间是否成功。对于幂等的生成请求,可以有限次数重试;对于可能产生外部副作用的业务操作,必须先设计幂等键或去重机制。
一般不建议重试400、401、403和明确的404,因为重试不会改变请求内容或权限状态。
三、检查三家接口的结构差异
GPT、Claude、Gemini 的接口风格并不完全一致,即使都通过 HTTP 调用,也不能只替换 URL 和模型名。
常见差异包括:
- GPT 可能使用 Responses 或聊天补全类接口。
- Claude 通常将消息、系统提示和版本头分开处理。
- Gemini 的内容块、生成配置和安全设置字段有自己的结构。
- 流式响应可能使用不同的事件格式。
- 工具调用、图片输入、结构化输出的字段名称和嵌套方式各不相同。
因此,适配层至少应抽象出以下内容:
统一输入:system、user、附件、工具定义 服务适配:endpoint、headers、request_body 统一输出:text、usage、finish_reason、request_id 错误映射:authentication、validation、quota、transient不要为了“兼容”而悄悄丢弃字段。对于不支持的能力,应在适配层明确返回错误,让调用方知道是功能差异,而不是模型随机失败。
四、排查上下文长度与输出限制
长文本请求常见问题包括:
- 输入超过当前模型上下文限制。
- 输出上限设置过大,超过账户或模型允许范围。
- 历史消息重复拼接,导致请求快速膨胀。
- 多模态内容的实际令牌消耗高于预估。
- 代理层或网关限制了请求体大小。
建议在发送前记录:
- 字符数和估算令牌数
- 历史消息条数
- 附件大小与类型
- 请求体字节数
max_tokens或等价输出限制
验证时先用极短输入,再逐步增加历史消息和附件。这样可以判断问题来自基础调用,还是来自上下文规模。
五、检查响应解析与流式处理
接口返回 HTTP200,不代表业务一定成功。仍需检查:
- 响应 JSON 是否完整。
- 是否存在错误对象或安全过滤状态。
- 文本字段的路径是否符合当前接口。
- 使用流式模式时,是否正确处理事件边界和结束事件。
- 是否把增量文本误当成完整文本重复拼接。
- 是否正确读取 usage、finish reason 和 request ID。
解析器应对缺失字段保持明确行为:返回可诊断错误,或使用经过定义的默认值。不要用宽泛的except Exception把真正的字段变化吞掉。
六、记录足够的诊断信息
一次可复现的日志至少应包含:
- 请求开始和结束时间
- HTTP 状态码
- 服务商和模型 ID
- 请求体大小
- 输入、输出令牌统计(若服务提供)
- 重试次数
- 响应中的 request ID
- 脱敏后的错误类型和错误消息
以下内容不应进入普通日志:
- 完整 API Key
- 用户的身份证件、密码、支付信息
- 未经授权的内部文档
- 不必要的完整提示词和原始附件
只处理你有权处理的数据,并确认日志保留周期符合项目要求。
七、配置独立于代码
建议通过环境变量或密钥管理系统配置:
AI_PROVIDER AI_API_URL AI_API_KEY AI_MODEL AI_TIMEOUT_SECONDS AI_MAX_RETRIES AI_MAX_INPUT_TOKENS启动时做一次配置校验:
- 必填项是否存在。
- URL 是否使用预期协议。
- 重试次数和超时是否在合理范围。
- 模型 ID 是否为空或包含意外空格。
- 生产环境是否误用了测试配置。
配置变更应可追踪,避免“本地能用、部署后失败”却无法判断到底改了什么。
八、需要多家服务时如何做可重复验证
如果项目需要比较不同服务的请求结构或计费信息,可以把每次测试固定为同一份输入、同一套输出限制和同一记录格式。这样得到的是工程层面的可比数据,而不是未经控制的模型排名。
当你需要一个独立入口来核对当前支持的工具和计费信息时,可以选用 moli。它是独立的第三方服务,不代表 OpenAI、Anthropic、Google、CSDN 或任何模型提供商;该链接仅作为可选的信息核对入口,具体支持范围和费用仍应以页面及上游文档为准。
九、推荐的完整排查顺序
遇到新错误时,按下面顺序执行:
- 保存完整状态码、响应头和脱敏响应体。
- 用最小输入确认网络和认证。
- 单独验证 URL 路径和模型 ID。
- 对照当前文档检查请求体字段。
- 检查上下文长度、输出上限和附件大小。
- 暂时关闭流式输出,先验证普通响应。
- 检查配额、并发和账户状态。
- 仅对明确的临时错误进行有限重试。
- 将成功请求固化为自动化测试。
- 恢复业务参数,逐项增加复杂度。
十、发布前自检清单
- 没有把 API Key 写入代码仓库、截图或公开日志。
- 使用的是当前文档中的接口路径和参数。
- 已区分网络错误、认证错误、请求错误、配额错误和服务端错误。
- 重试逻辑遵守服务端提示,并避免重复执行副作用操作。
- 记录了 request ID、耗时和脱敏后的错误信息。
- 对上下文长度、附件大小和输出限制做了边界测试。
- 明确告知用户能力、可用性、上下文限制和价格可能变化。
- 只使用自己有权处理的数据和凭据。
- 在真实发布前完成了人工复核。
把排查过程从“反复试参数”变成可记录、可复现、可验证的流程,通常比更换 SDK 或模型更快找到根因。