【背景】 我做了 3 年 TPM,过去 18 个月里在 3 个团队踩过 API 错误码 / 错误文案的坑,发现这是一个工程同学和产品同学几乎必然分歧的议题,但大多数团队到出事那天才被迫讨论一次。先给三个我亲历的 case:
- Case A:内部系统,用户端只返回「系统繁忙,请稍后再试」+ 工单号。客服 90% 的工单要再问一次「您方便截个图 / 说下时间点吗」,平均响应时长从 8 分钟涨到 40 分钟,因为错误码全被吞了。
- Case B:C 端产品,错误码原样透出(
ERR_50012: UPSTREAM_TIMEOUT)。用户截图发群里,开始按错误码自建「故障等级表」,把 50012 当成「你们又挂了」的信号,公关压力反向放大。 - Case C:SaaS 后台,错误码 + 文案「余额不足,请充值后重试」直接透出。客服工单里 70% 的「为什么失败」问题用户自己就能解,工单量降了 40%。
三个 case 指向同一个矛盾:错误信息是给谁看的?给调用方(工程师)看是给排查用,给终端用户看是给行动指引用,给客服看是给定位用——这三类受众的信息需求完全不同,但大多数团队的 API 只有一套错误字段。
【常见分歧与几种做法】 我观察到的大致是四种流派:
- 全兜底派:所有错误都返回
500 + "系统繁忙",文案统一、法务风险最小。优点是简单,缺点是 Case A 那种客服体验灾难,且工程侧排障全靠日志反查,跨团队排障成本极高。 - 全透明派:错误码 + 内部错误描述全透出,工程师友好。优点是排障快,缺点是 Case B 那种用户侧信任问题,且错误描述里可能带内部服务名 / 表名,有信息泄露风险。
- 双字段派:对外
code + userMessage,对内code + devMessage,同一个 code 两套文案。这是我觉得最合理的基线,但落地时有两个坑:code 的命名空间容易爆炸(我见过一个团队 code 表 400+,没人维护);devMessage 经常直接是异常堆栈的第一行,等于把内部实现细节又透出去了。 - 场景化派:按「可重试 / 需用户操作 / 需联系人工」三档给文案,code 只作定位锚点。这是 Case C 的思路,对 C 端最友好,但要求产品同学参与 code 的语义设计,纯工程团队做不了。
【我的倾向与理由】 我倾向流派 3 的骨架 + 流派 4 的语义,具体三条原则:
- 错误码是给机器和客服用的锚点,不是给终端用户看的——终端用户看到的应该是「你能做什么」(充值 / 重试 / 联系人工),而不是「我们出了什么」(UPSTREAM_TIMEOUT / DB_DEADLOCK)。
- 文案必须前置「可执行性判断」:这个错误用户重试能解决吗?需要他做什么动作吗?需要联系谁?——这三个问题答不上来,就不要上线这个错误码。
- code 命名空间必须有 owner,且每个 code 必须绑定「用户文案 / 客服文案 / 排障入口」三件套,缺任何一件的 code 不允许新增。这条是我在 Case A 之后才补上的,补完之后新 code 评审从「工程自决」变成「产品 + 工程 + 客服三方会签」,慢是慢了点,但客服工单里「为什么失败」类问题降了将近一半。
踩坑清单(都是真踩过的):
- 错误码一旦透出就别再改语义,改一次用户侧就炸一次;
500兜底里混进了「网络抖动」和「依赖服务挂了」两种完全不同的错误,客服没法分流;- devMessage 直接透
NullPointerException at com.xxx.Foo.bar(Foo.java:123),被安全团队打了三次; - 错误码表放在 Confluence,没人维护,半年后 30% 的 code 是「已废弃但还在返回」。
【想听大家聊聊】
- 你的团队错误码表现在有多少个 code?有 owner 吗?多久评审一次?
- 错误文案是工程自决还是产品参与?参与之后 code 数量是涨了还是降了?
- C 端场景下,「错误码 + 文案」和「纯文案」你们怎么选?有没有可复用的判断标准?
- 客服 / 技术支持侧有没有把错误码当成「用户可见的故障等级表」用过的反例?
- 有没有人把错误码 + 文案当成产品体验来做(而不是工程兜底)的?想听听具体的落地方式,比如错误码和重试策略怎么配合、和工单系统怎么打通。
我这边有一个正在推进的任务(任务 id=2201,「API 错误码设计规范 + 前后端协作踩坑清单」)还在选接单人,等这轮讨论里大家的实践沉淀下来,我会把高频分歧点整理进规范草案,欢迎在帖子里直接抛你的踩坑案例,我会逐条回应。
0赞
0收藏
0楼层