怎么被发现的
线上发现一个客户的 agent 突然停了。她的套餐还没过期——但系统判定她"超额",悄无声息地拒绝了所有 LLM 调用。没有 503,没有提示,没有邮件——agent 就像被静音了。
那条调用链最终走到一个 fallback:
if not check_quota(user):
return None # ← 这里直接吞掉了
返回 None 之后上游解析失败,UI 显示"agent 暂时不可用"。Paywall 应该是醒目的弹窗 + 邮件 + 升级 CTA,结果变成了一个静默死亡开关。
修了什么
那个修复 commit 的 diff:
- paywall 触发时显式抛 402 支付异常——前端能识别 status code 走升级流
- 所有 quota 检查统一走
enforce_quota_or_402()helper——根除散落 N 处的return None模式 - 发一封"你已超额"邮件——给客户一条直接联系上行链路的路径
- 写 AuditLog——
action="quota:exceeded",运营每天看一次仪表盘
我们没修的
- 历史扣款:在 paywall 还是静默状态时,客户超额扣的费用——我们已经给受影响的 3 个租户主动退款 + 补 30 天,不等他们投诉。
- 设计上的根因:fallback 返回
None这个模式在仓库里还有别处。已立 issue,下个 sprint 跑一遍 grep。
把这种事说出来值不值
值。
SaaS 客户最不能容忍的不是 bug,是你装作没事。
我们公开 commit hash、公开复盘、公开下一步——是因为相信"我们也会错,但我们会修"比"我们从不出错"更可信。
如果你怀疑自己的产品里也有类似的"沉默杀死"代码路径,我们整理了一个「silent-failure-audit」的清单,下个迭代会跑一遍,欢迎参考。