尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI接口402报错全解析:额度耗尽的排查、处理与预防

AI接口402报错全解析:额度耗尽的排查、处理与预防 先贴一下今天这篇文章的由头。不少朋友最近在调AI接口的时候应该都被这么一串error砸过脸{error:{code:402,message:Your prepayment credits are depleted.}}翻译成人话就是你的预付费额度用完了服务端拒绝继续给你出结果。这个错很有辨识度code是402message里的prepayment credits depleted指的就是预付费点数余额清零。第一次遇到它的人很容易慌会怀疑是不是代码写错了、是不是并发太高把服务打崩了。实际上大概率都不是这个错跟你的业务逻辑没太大关系而是“钱”的问题。这篇东西就专门聊聊这种报错该怎么定位、怎么处理、怎么提前预防适合正在做AI应用集成的后端开发、独立开发者以及所有把第三方API当基础设施用的同学。1. 402错误到底在说什么1.1 从HTTP状态码说起402这个数字其实挺冷门的。HTTP状态码从1xx到5xx大家最熟的是200、301、404、500。而402 Payment Required在HTTP协议里是一个被保留但长期没被广泛使用的状态码意思很直白“这个请求要付钱但你还没付够。”早期Web世界基本没人用它因为绝大多数网站都是登录后随便看的不存在按次计费这种事需要付费的内容也通常是先鉴权再决定给不给看走的是403。但到了API时代402一下子活了。尤其是大模型API、短信验证码、云函数、图片处理这类按量计费的服务服务商需要一种明确的HTTP状态来告诉客户端“你的请求我收到了逻辑上也允许但你的账户钱不够了所以我不会继续执行。”如果用200返回错误客户端得解析业务code麻烦如果用403又和“没权限”混淆。于是402成了事实标准。你现在在很多主流AI API的SDK里看到402就是这个原因。这里我想补充一个容易被忽略的点HTTP状态码是服务端对本次请求的最终评价但它不一定是业务结果。有的平台会把计费错误的HTTP状态故意设成200然后在body里塞一个业务错误码这时你如果只按状态码做判断逻辑上没问题但排错会很痛苦。所以看到任何API报错第一件事永远是看完整的响应体而不是只盯着状态码或者SDK里那句简短的异常文案。1.2 prepayment credits彻底拆解接着拆message里的关键词。Prepayment是预付费credits在API语境里翻译成“点数”或“额度”比“信用”更贴切。整个模型是这样运作的你先往账户里充一笔真实货币平台按汇率把人民币或美元换算成credits然后你调用接口时服务端根据模型单价、输入输出token数、请求次数等维度从你的credits余额里扣。depleted就是“耗尽”。额度用完后服务端不会“赊账”继续跑而是直接拒绝。你可以把它类比成话费打个长途余额不足就被掐线运营商不会因为你信誉好就先让你欠着打完这通电话。API也一样而且比话费还要严格——话费欠费了有时候还能接听API额度清零后连一个token都不给你多生成。这里还要留意一点credits并不都是“充多少钱就是多少点数”。很多平台在充值之外还有免费赠送额度、活动积分、订阅套餐包含的额度。这些不同来源的额度通常有不同的有效期和抵扣顺序。比如平台普遍的做法是先用免费额度再用付费额度。于是会出现一种很诡异的场景你明明充了钱余额显示还剩不少但接口依然报“prepayment credits are depleted”。原因往往是免费额度先被扣光了而你的付费额度因为结算周期问题还没生效或者被冻结在待出账的账单里。这个后面在踩坑部分会详细讲。1.3 不要和401、403、429搞混搞清楚“这是什么”之后更重要的其实是“它不是什么”。很多新手排查402时会把它和另外几个高频报错混在一起导致排查方向完全跑偏。我整理一张表你们可以直接存下来状态码典型message含义一句话处理401invalid_api_key / token expired你是谁凭据无效检查API key、token重新生成即可403permission denied / forbidden你是谁知道了但这件事不让做查账号角色权限、资源授权范围402prepayment credits depleted钱不够了没法继续执行充值、升级套餐、等账单结算429rate limit exceeded / too many requests短时间内请求太多被限流了退避重试、申请提高配额5xxinternal server error / service unavailable服务端自己出问题了等待、提工单、不要反复重试区别的关键在于401是“身份”问题403是“权限”问题429是“频率”问题402是“余额”问题。前两者你改代码能解决后两者改代码一般都解决不了。看到402或者429第一反应应该是打开控制台看账户状态而不是打开编辑器找bug。2. 额度耗尽类报错的完整排查思路2.1 先确认错误发生在哪一层拿到一个402报错先别急着登录控制台先做一步定位工作这个错误到底是从哪一层冒出来的我把它分成三种情况。第一种是SDK内部抛出来的。比如你在Python里用了某个官方SDKSDK收到HTTP响应后把非2xx状态码封装成异常抛出来。这时候错误信息里通常已经带了服务端返回的原始body定位相对容易。第二种是API网关或代理层返回的。如果你的服务前面挂了网关或者用了聚合API平台网关本身也可能返回402风格的错误。这时候你没法确定上游服务商是不是真的拒绝了请求因为网关可能只是透传也可能是它自己做的计费拦截。建议先看网关日志里有没有upstream的响应体再决定是查自己的网关配置还是查上游账户。第三种是你自己写的重试逻辑里报出来的。比如你封装了一个HTTP客户端对非2xx状态统一重试三次最后一次失败后业务层抛错。如果你没有把原始响应体透传出来只抛了一个笼统的“请求失败”那后续排查难度直接翻倍。所以我的建议是所有第三方API的封装层最后抛出的异常必须包含HTTP状态码、原始响应body、request_id、目标URL这四个信息缺一个都算封装不合格。这一步的产出是一个结论错误来自服务端而不是本地网络或代码逻辑。如果你发现连请求都没发出去那根本不可能收到402那就是另一套排查方法了。2.2 核对账号余额与账单状态确认是服务端返回的402后接下来就是查账户。登录服务商的控制台找“账单Billing”、“用量Usage”、“余额Credits”这几个入口。重点看三块数据当前可用余额今日/本周期已消耗的额度有没有未出账或冻结中的扣费记录。有些服务商提供了API查询余额的接口能省去人工登录的麻烦。比如一部分平台的接口风格类似curl -H Authorization: Bearer $API_KEY \ https://api.example.com/v1/credits返回的JSON里通常会包含total granted、total used、total remaining这类字段。如果你用的是这类平台完全可以写一个定时脚本去拉余额低于阈值就告警比人肉盯控制台靠谱得多。这里有一个重要的心理预期余额刷新是异步的。你充值之后、或者刚跑完一个大任务之后控制台显示的余额不一定立刻更新。有时扣费事件要过几分钟才会入账有时支付回调延迟钱已经扣了但额度还没到账。所以看到余额和报错矛盾时别急着下结论说“系统有bug”先刷新几次、等几分钟再结合账户的流水记录判断。2.3 检查计费模式与额度重置周期查完余额还要搞清楚你的额度到底是怎么来的。我把常见计费模式分成三类一次性预付费充多少钱换多少点数用完再充。这种模式下depleted就是真的没钱了处理方式只有充值或换key。订阅套餐送额度每月固定费用套餐内包含一定数量credits月初重置。这种模式最容易出现“月底突然报错”的情况因为额度是按月算的你月初一口气用完剩下的日子就只能干瞪眼。混合模式有免费赠送额度也有付费额度抵扣顺序由平台规则决定。免费额度用完后继续调用就会报预付费额度不足的错——哪怕你账户里其实还有付费额度。第三类最容易让人困惑。我见过一个案例某平台给新用户送了5美元的免费额度用户充了20美元进去控制台显示余额25美元。结果免费额度在第三天花完后接口立刻开始报402。控制台总余额明明还剩20美元为什么说“depleted”就是因为抵扣顺序优先用的是免费额度免费额度清零后系统不会自动无缝切换到付费额度而是先返回一个错误让你知道“免费额度已经用完了”。这种场景的处理方式不是充值而是去后台把计费状态调整成“允许使用付费额度”。所以在处理402之前花两分钟把你的账户套餐类型、免费额度规则、重置日期都查清楚。这会帮你省下后面至少半小时的弯路。2.4 四个常见误区排查阶段最容易踩的几个坑我一起列出来误区一反复重试。看到402后写个for循环重试十次这纯属浪费额度。每次重试都会真实地打到服务端虽然服务端不会继续生成内容但有些平台会记录请求次数甚至扣极小的调用费。重试不但解决不了问题还可能触发429限流把局面搞得更复杂。误区二只盯着message不看code。message是给人看的code是给程序看的。如果服务端返回的是JSON格式的错误体你要以error.code为准而不是以肉眼理解message为准。误区三把402当成网络问题。这个错误发生在服务端的鉴权和计费阶段和你的网络环境没有任何关系。你在办公室调、在家里调、用4G调结果都是一样的。排查网络只会浪费时间。误区四忽略request_id等上下文信息。大多数正规API的错误响应里都会带一个request_id或error_id这是后续提工单时服务商定位问题的唯一凭据。出现402时顺手把这个ID记下来如果后续发现是误扣费一张工单就能解决没有这个ID客服也很难帮你查。3. 实操从报错到恢复服务的完整处理流程3.1 场景还原凌晨两点的一次全线故障我给你还原一个我踩过真坑的场景。当时我在维护一个公司内部的AI问答机器人平时跑得好好的结果某天凌晨两点运维群里突然开始刷告警所有用户都反馈“答不了题”。打开日志一看满屏都是同一个错误{error:{code:402,message:Your prepayment credits are depleted.}}第一反应当然是查代码。因为白天刚发过一个版本我怀疑是发布改了什么导致请求参数出了问题。查了半天还对比了之前正常时的请求日志发现请求参数完全正常。接着我又怀疑是某个Key被限流了换了key来测依然报402。最后一脸茫然地登录控制台看到余额的瞬间才明白免费试用额度已经清零了而付费额度因为绑定的信用卡到期没有扣款成功整个账号等于进入了欠费停服状态。这次事故给我的教训特别深。把额度当作基础设施的一部分它和数据库连接、缓存、消息队列一样属于服务依赖必须监控、必须有告警、必须有预案而不是用了再担心。3.2 推荐的处理路径分步走遇到402时按下面这个顺序处理效率最高止损如果是生产环境立刻把请求切换到备用key或备用服务商。没有备用就先降级处理比如对用户的请求做排队或缓存尽量不要让用户看到“服务直接崩了”。取证把完整的错误JSON、时间点、request_id、账号标识记下来。不用急着分析先留着后面充完值复盘用得着。查账户登录控制台核对应付余额、可用余额、订阅状态、支付方式是否失效。补充额度根据账户类型选择充值、升级订阅、联系销售开票。如果是自动充值失败的场景换一张有效的支付方式后触达充值即可。验证恢复先发一个最小的请求确认返回200后再放流量。别一充完值就直接全量放量万一上游还没刷新过来用户看到的就是反复横跳。复盘配置余额告警原则上当余额低于阈值我习惯设20%时就触发通知而不是等归零了才靠用户投诉发现。这个流程里最容易被跳过的就是第1步。很多人遇到报错的第一反应是“我要搞清楚为什么”但生产环境的优先级永远是把影响面控制在最小范围。先切流量、再查原因才是对的顺序。3.3 代码层面怎么统一兜底在业务代码里我强烈建议统一封装一个处理“支付相关错误”的异常类。比如用Python时可以这样写class PaymentRequiredError(Exception): def __init__(self, status_code: int, body: dict): err body.get(error, {}) self.code err.get(code) self.message err.get(message, ) self.request_id err.get(request_id, ) super().__init__(f[{self.code}] {self.message}) # # 在统一封装的调用函数里捕获这个错误 # def call_ai_api(prompt: str) - str: resp requests.post( https://api.example.com/v1/chat/completions, json{model: gpt-4o, messages: [{role: user, content: prompt}]}, headers{Authorization: fBearer {API_KEY}}, timeout30, ) # 将异常往上抛由上层统一处理告警与切换 if resp.status_code 402: raise PaymentRequiredError(resp.status_code, resp.json()) resp.raise_for_status() return resp.json()[choices][0][message][content]上层调用方可以这样处理try: answer call_ai_api(user_input) except PaymentRequiredError as exc: # 触发告警发送到企业微信/Slack/钉钉 alert_ops(fAPI额度耗尽request_id{exc.request_id}, message{exc.message}) # 自动切换备用key或备用服务商 if BACKUP_KEY: answer call_ai_api_with_key(user_input, BACKUP_KEY) else: answer 对不起服务暂时拥挤请稍后再试。这个封装有三个好处第一支付类错误和业务类错误被区分开不会被统一当作普通IO异常处理第二告警信息里带上了request_id后续排查可以直达最底层第三切换备用key的逻辑不会污染正常调用路径。这套做法不依赖任何框架你可以照搬到Java、Go、Node.js里。3.4 临时降级方案别让服务彻底断掉如果充值来得及那没问题如果充值通道有问题或者上游服务商整体故障你得有降级预案。我见过这几个比较实用的做法切备用服务商同类AI API不止一家提前注册一两家同类型服务把key放进配置中心。平时不用出了事一键切换。这里注意切换后模型能力可能有差异最好提前在代码里做好模型名映射别到时候手忙脚乱改参数。本地模型兜底如果只是做简单问答、摘要、分类这类常见任务本地部署的小模型也能顶一阵。市面上的本地推理工具不少比如LM Studio之类可以直接在本地起一个兼容接口。效果跟云端大模型有差距但至少能保证服务不挂。业务降级设定一个“仅白名单用户可用”的开关把有限的余量留给付费用户或核心渠道。其他用户排队、转人工、或者返回一个“稍后再试”的提示。虽然体验变差了但比全量瘫痪要体面得多。这些方案的关键在于“预案前置”。真出故障的时候再去调研怎么部署本地模型、怎么申请备用key那就晚了。平时把备用基础设施准备好问题发生时只是点一个开关的事。4. 同类API错误排查对照与避坑经验4.1 高频API错误对照速查表把最近开发者社区里讨论热度比较高的几个报错整理了一下做成一张速查表。这些错误我都遇到过至少一次处理思路都是通用的报错原文关键词状态码含义优先排查动作invalid_api_key / authentication failed401API key无效或过期核对key、重新生成key、检查key是否被误删unsupported_country_region_territory403账号或部署环境涉及服务范围限制查服务商官方文档核对可用范围联系客服确认账号配置prepayment credits depleted / insufficient balance402预付费额度不足充值、检查免费/付费额度抵扣顺序rate limit exceeded / quota exceeded429请求频率或配额超限退避重试、申请提高配额、查用量曲线stream disconnected before completion / transport error500流式响应中途断连常见于网络链路不稳定看超时设置、断点续传、重试策略确认网络链路与DNStoken exchange failed400登录/授权时令牌交换失败授权链路过期或不完整刷新登录态、重新走授权流程、确认授权来源有效internal error / service unavailable500/503服务端自身故障提工单带request_id避免短时间高频重试这张表的共同点是每个错误类型都有主攻方向不要在不相关的方向上浪费时间。比如token exchange failed很多人第一反应是改代码实际通常是账号授权过期或登录凭证失效重新登录一次就好了。stream disconnected这类错误则要结合客户端日志里的重试次数来判断偶尔一次是网络抖动频繁出现就要检查网络环境了。4.2 五个真实踩过的坑说几个我实实在在经历过的坑希望能帮你提前绕开。第一个坑总余额看着够但接口执意报depleted。原因前面提过免费额度和付费额度是两套账。控制台显示的总额可能很充足但免费额度那一列已经归零系统默认先耗免费额度耗完以后不会自动切到付费额度而是直接返回402。解决办法是去账户设置里找“计费模式”或“默认用量偏好”确认是否允许使用付费额度。第二个坑充值后马上用依然报错。支付回调不是即时的。我从实际经验来看多数平台5到15分钟内会到账个别渠道可能拖到小时级。如果你充完值立刻测试发现还是402不要急着再充一笔。先看支付订单状态确认交易是否已经成功如果成功就等一下最多等半小时再试。反复充值很容易冲成双倍退费还得走工单非常麻烦。第三个坑一个key报错以为所有key都废了。有些平台是“账号级共享余额”所有key共用同一份额度也有些平台支持按项目隔离额度。如果你用的是后者一个项目key报402其他项目可能完全正常。不要因为一个key报错就把整个服务降级先确认额度隔离粒度。第四个坑把错误重试写成了死循环。有同学在代码里对402也做了自动重试且没有设置最大次数。结果余额耗尽的晚上日志里刷了几千条同样的请求把日志系统都差点打爆。正确做法是对402这类错误不做自动重试而是触发告警和人工介入。只有网络类错误才适合自动重试而且必须限制次数。第五个坑忽略请求量的突然增长。很多额度耗尽并不是正常消耗而是某个业务逻辑出了bug比如一个定时任务在循环里重复调用API一个小时就把一星期的额度烧光了。这种情况下的真实问题不是“该充值了”而是“哪个代码写错了”。所以看到余额断崖式下降时先查用量明细找到消耗最大的请求来源修复根因后再谈充值。4.3 给监控告警提几点建议额度相关的监控我建议至少做三层。第一层是余额监控。定时拉取额度接口低于设定阈值就告警。这个动作可以用云函数的定时触发器来跑十分钟一次即可成本可以忽略不计。第二层是失败率监控。在API调用封装层统计每分钟的失败数量和状态码分布一旦发现402或5xx占比超过某个阈值立刻触发告警。这比余额监控更快因为它能捕捉到充值成功后依然异常的前几分钟。第三层是消费速率监控。不光看余额还要看余额消耗速率。如果某一天消耗量是前一天的十倍即使余额暂时还够也说明有异常值得人工看一眼。这类数据通过日志聚合平台都能轻松算出关键是你要有意识去建这个指标。5. 关于这个报错我的一些体会第一次被402支配的那个凌晨我花了整整两小时查代码最后发现是余额没了。从那以后我就明白了一件事调第三方API本质上是在跟另一个团队的基础设施打交道。你不能控制他们的计费系统什么时候出问题、不能控制他们的支付渠道回调有多慢但你可以控制自己对错误信息的敏感度以及预案的成熟度。我现在处理这类报错的原则很朴素所有外部依赖必须可观测、可降级、可快速恢复。额度账户要监控备用key要常备支付信息要定期检查有效期新项目接API时第一件事就是把错误处理的骨架搭好而不是等到线上炸了再补。402这个错误其实是个很善良的报错它把一个非常清晰的问题直接拍在你脸上钱不够了。相比之下那些模棱两可的5xx错误反而更难搞。最后分享一个小技巧如果你用的是按月重置免费额度的API服务可以在日历里设一个每月的提醒重置日过后的第一周专门看一眼用量趋势估算本月的消耗速度和够不够撑到月底。提前把额度分配好比月底临时充值要从容得多。希望这篇东西能让你下次再看到那串JSON时不再心头一紧而是面无表情地打开控制台、充个值、完事。
返回列表