早上刚到工位,豆浆还没插吸管,手机“叮叮叮”弹出三条告警——API调用失败率飙到15%。你一把拉开椅子坐下,脑子里飞速闪过:是配额爆了?密钥废了?还是大模型那头又抽风了?
别慌。我过去三年守着几个日请求量上千万的聚合平台,见过的报错比吃过的外卖还多。今天不扯虚的,直接把你最常撞上的那几个报错拎出来,连原因带解法,一顿饭的功夫给你捋明白。
报错一:401 Unauthorized 或 Invalid Authentication
这俩一出现,大概率是钥匙拿错了。
最常见的情况:API Key复制漏了一位字符,或者Key本身没激活就上线用了。还有更隐蔽的——你用的Key是旧版格式,但平台最近升级了JWT鉴权,老Key直接失效。
怎么办?
先去控制台重新生成一个新Key,粘贴时多检查头尾有没有多余空格。如果用了环境变量,echo $YOUR_KEY 看一眼对不对。
另外,有些平台区分“API Key”和“Organization ID”,两个都得填对位置。别笑,我真见过把Org ID塞进Key字段的。
报错二:429 Too Many Requests
这个翻译成人话就是:你太猛了,服务端扛不住。
RPM(每分钟请求数)或TPM(每分钟Token数)超限。很多初学者一上来就开100个并发,觉得“这才哪儿到哪儿”,结果平台直接给你限流。
解法分三层:
第一层,代码里加指数退避重试。别用固定间隔,用 2^retry_count * 初始延迟 这种节奏,给服务端喘气的时间。
第二层,把请求打散。比如原本集中在前5秒的请求,拉长到30秒均匀分布。
第三层,上多路Key轮询。如果你聚合了多个渠道商的Key,搞个简单的round-robin,压力自然分散。
顺带提一嘴,别一上来就冲平台客服喊“扩容”——先确认自己的使用量是不是真的在合同范围内。
报错三:400 Bad Request — Invalid prompt 或 Content filtering
这种是请求体本身出了问题。
Invalid prompt多半是JSON结构不对——少个花括号,或者messages数组里漏了role字段。这时候把请求体扔到JSON校验器里扫一遍,比瞪眼找快得多。
Content filtering就敏感了。你传的提示词里带政治、暴力、色情擦边内容,或者越狱指令被安全策略拦了。不是说你故意的,有时候翻译任务里蹦出个敏感词,模型直接拒答。
解法:精简你的system prompt,去掉所有试探性措辞。如果业务确实需要涉及某些领域,走工单向平台申请白名单,别硬闯。
报错四:503 Service Unavailable 或 504 Gateway Timeout
这俩是服务端挂了,或者你这边网络太拉胯。
503说明模型服务真宕了,或者正在做灰度发布重启。这时候你重试也没用,等个一两分钟再试。
504更常见——你的请求里max_tokens设了8000,模型在那吭哧吭哧生成,中间网络超时断开。
我的做法:把超时时间从默认的60秒拉到180秒,同时在代码里区分“连接超时”和“读取超时”,前者短一些(比如10秒),后者给足。
如果频繁出现,拿你的请求体去平台上做playground测试。playground能通但API不通,检查你的网关代理;两边都不通,那大概率是模型集群在抖动,切备用渠道。
报错五:402 Payment Required — 余额不足或配额耗尽
这条最扎心,因为要掏钱。
很多平台是按预付费扣的,你的账户余额低于阈值时调用直接拒。别等到报错才看账单,提前设好告警——比如余额低于50元就邮件+短信轰炸你。
还有一种情况:你开了“按Token后付费”模式,但日消费上限设死了,当天额度用光也会报402。解法简单,去控制台提额,或者手动重置周期。
一些让你少熬夜的隐性坑
上面是台面上的报错,我再送你几个台面下的经验。
流式响应(SSE)没正确处理:你开了
stream=True,但客户端按普通JSON解析,直接报解析异常。记得用eventsource类库逐行读data:开头的行。代理和DNS解析:国内环境调海外模型,代理挂了或者DNS被污染,报错可能是
ConnectionError而不是业务错误。弄个备用代理池,或者直接用专线通道。模型版本别名:你代码里写
model=gpt-4,但平台最近把别名指向了gpt-4-turbo,而turbo的上下文窗口不同,你的max_tokens超了,报context_length_exceeded。每次平台发更新公告,扫一眼影响项。
遇到未知报错时的三板斧
如果报错码不在文档里,别死磕。
第一板斧:把完整报错体(含request_id)贴到平台状态页或官方论坛搜索,很多时候是已知问题。
第二板斧:切备用模型或备用渠道商。我的聚合平台至少对接三家,主模型挂了自动路由到次选,用户端几乎无感。
第三板斧:写个本地mock服务,用相同请求体打自己的桩,排除代码逻辑问题。桩能过但真实API过不了,锅就是平台方的。
最后唠叨一句:日志要打全。每次请求的request_id、模型名、Token用量、耗时,全部结构化存下来。出事的时候,没有日志就像晚上停电找螺丝刀——光摸黑就耗费大半精力。
好了,咖啡见底,今天的坑就填到这儿。下次再遇见报错,先看一眼状态码,再对号入座翻这篇,八成能把你从工位前捞回来。要是还有活久见的奇葩问题,评论区扔过来,我帮你拆。