
API错误码设计详解互联网前后端与微服务协作里错误怎么表达直接影响联调效率、监控质量和用户体验。成熟团队通常遵守一条分工HTTP 状态码描述传输与协议层业务code描述应用语义统一 JSON 信封让前端、网关、监控都能机器处理。本文面向全栈与架构读者不限定某一语言框架覆盖单体到微服务、从设计原则到中心化治理与业界方案。适用于REST / JSON、BFF / 网关、gRPC / Thrift等常见形态语言栈可替换。速览成功本文约定code 0国内常见云厂商 API 亦常见HTTP 200 且无业务 code或code: OK——团队按历史包袱选型即可。业务失败常见HTTP 200 code≠0鉴权/限流/下游不可用用对应 HTTP 状态码。前端用code分支不要用message字符串匹配。微服务错误要可追溯、可归属、不吞下游语义traceId标配。治理错误码是API 契约宜 YAML/Proto 中心化 CI 生成常量。目录1. 两层错误HTTP 与业务码2. 设计原则3. 统一响应结构4. 错误码如何编号5. 后端全局异常与分层6. 前端拦截器与分支策略7. 两种流派与生产折中8. 微服务挑战与传递规范9. 中心化错误码治理10. 与 OpenAPI、监控联动11. 业界方案速览12. 反模式13. 落地阶段建议14. 名词速查卡1. 两层错误HTTP 与业务码层次谁关心典型值作用HTTP Status浏览器、CDN、网关、爬虫200、400、401、403、404、429、502、503协议与基础设施语义业务code前端逻辑、产品文案、业务监控0成功20002密码错误具体业务分支HTTP 401/502HTTP 请求网关 / BFF业务服务JSON: code message data traceId前端按 code 处理不要把所有失败都塞进 HTTP 500也不要让前端只靠 HTTP 状态码区分「密码错误」和「库存不足」——后者应靠业务code。2. 设计原则原则说明唯一性一个code只表示一种错误禁止复用机器可读程序只认code/name常量不认自然语言人类可读message给展示与 i18n不参与核心分支逻辑不泄露内部禁止向前端返回堆栈、SQL、内网 IP、未脱敏路径可追踪响应与日志带同一traceId及可选spanId可扩展分段或命名空间新模块新区间避免撞号中心化定义在统一 YAML/Proto/仓库禁止各服务私造「通用码」进阶字段可选字段用途typeBUSINESS/SYSTEM/INFRA/AUTH/THIRD_PARTYretryable前端/客户端是否应退避重试suggest_action如跳转登录、展示表单错误3. 统一响应结构推荐 JSON 信封字段名可按团队微调但语义保持一致{code:20002,message:密码错误,data:null,traceId:a1b2c3d4e5f6}path请求路径可选调试环境可返回生产环境不少团队只在日志中记录 path响应体不暴露避免轻微泄露内部路由结构。字段说明code整数或字符串常量成功见下「成功约定」message默认提示文案可配合 i18n 键data成功时业务数据失败时常为null或结构化错误详情traceId全链路 ID用户报障与后端排障必备path可选生产宜仅写日志成功约定本文示例以code: 0表示成功国内前后端协作极常见。Google Cloud API、AWS 等更常采用HTTP 200 业务体直接返回无额外code或字符串OK。选定一种后全公司统一即可避免同一产品两套信封。成功示例{code:0,message:ok,data:{userId:u_123},traceId:a1b2c3d4e5f6}4. 错误码如何编号4.1 分段数字国内常见0 成功 1xxxx 通用参数、鉴权、系统 1000 参数校验失败 1001 未登录 / Token 过期 → 常配合 HTTP 401 1002 无权限 → 常配合 HTTP 403 1003 资源不存在 → 常配合 HTTP 404 1004 请求频率超限 → 常配合 HTTP 429 1999 系统内部错误 → 常配合 HTTP 500 2xxxx 用户模块 20001 用户不存在 20002 密码错误 3xxxx 订单模块 30001 库存不足 30002 订单已取消小团队可简化为0 按模块预留区间如用户10001–10999、订单20001–20999。4.2 结构化长码格式示意[级别][模块][序号]例如2011002→ 业务(2) 用户(01) 密码错误(002)。4.3 字符串码可读性优先如B-USER-PASSWORD_WRONG、ORDER_STOCK_NOT_ENOUGH。适合 OpenAPI 文档与跨语言常量名对齐注意大小写与命名规范统一。5. 后端全局异常与分层各语言框架实现不同但职责分层一致异常类型典型映射对外注意参数校验失败code1000HTTP400或 200可带字段级data.errors业务异常BizException携带注册过的code message多为 HTTP200或 400未捕获异常记完整日志对外1999或通用系统码绝不返回堆栈网关鉴权/限流401 / 403 / 429由网关或统一过滤器返回标准 JSON下游超时/不可用502 / 503与业务「库存不足」区分开伪代码语言无关try: return success(data) catch ValidationError as e: return envelope(codeINVALID_PARAM, http400) catch BizError as e: return envelope(codee.code, messagee.message, http200) catch Exception as e: log.error(traceId, e) return envelope(codeINTERNAL_ERROR, http500)禁止在业务代码里散落 magic number应引用中心化定义的ErrorCode常量。6. 前端拦截器与分支策略原则HTTP 层与业务层分开处理。// 示意axios 响应拦截functiononResponse(response){constbodyresponse.data;if(body.code0){returnbody.data;}switch(body.code){case1001:redirectToLogin();break;case20002:showToast(密码错误);// 或 i18n(body.message)break;default:showToast(body.message||操作失败);}if(body.retryable){// 可选指数退避重试注意幂等与上限scheduleRetry(requestConfig,body);}returnPromise.reject(body);}functiononHttpError(error){// 网络断开、502、504 等 — 非业务 codeshowToast(网络异常请稍后重试);}规则说明用code做switch不要if (message.includes(密码))非 2xx 进 HTTP 错误处理与 body 里code两条线上报带traceId用户反馈时复制 traceId 给支持/后端7. 两种流派与生产折中流派做法优点缺点全 200 body code成功/失败 HTTP 均为 200前端统一读 body国内联调习惯丢失 HTTP 语义网关难按状态过滤HTTP body code参数错 400、未登录 401业务细码在 bodyREST 清晰CDN/网关友好部分旧客户端对非 200 处理麻烦生产常见折中网关 / 鉴权 / 限流 / 路由不存在 →正确 HTTP 状态码可预期的业务失败余额不足、重复提交→HTTP 200 code≠0文档中写清每个接口的HTTP 与 code 组合避免前后端各自猜测8. 微服务挑战与传递规范8.1 特殊挑战挑战后果各服务自定规则BFF/前端大量映射 if-else中间层「吞」下游错误前端只见「系统异常」无法排障责任不清工单在网关、本服务、下游之间流转混乱缺统一 trace多服务日志无法拼成一次用户请求熔断与业务混淆用户不知应重试还是改参数8.2 传递原则谁出错谁定义中间层只包装不重写语义。跨服务错误体建议保留{code:30001,message:库存不足,service:inventory-service,original_code:30001,original_service:inventory-service,trace_id:abc123,span_id:def456}❌ 反例下游库存不足上游统一成{ code: 500, message: 系统异常 }。8.3 gRPC / Thrift 与 HTTP 归一化内部微服务大量采用gRPC或 Thrift 等 RPC错误模型与 HTTP JSON 不同但业务语义应同源协议常见载体建议gRPCstatus如INVALID_ARGUMENTmessagedetails在details/error_details中放业务code、retryable、trace_id可用google.rpc.Status 自定义 ProtoThrift框架异常 应用错误码字段与中心化 YAML/Proto 生成的常量对齐对外 RESTJSON 信封由BFF / API 网关将 RPC 错误归一化为本文 §3 结构勿让前端直接解析 gRPC status原则不变RPC 层保留original_code / original_service中间服务不吞下游业务语义。8.4 HTTP 状态码由谁决定场景HTTP说明网关鉴权失败401网关直接返回路由不存在404网关 / API 网关限流429网关业务失败200body.code ≠ 0下游不可用502 / 503网关或 BFF不要让每个微服务各自发明一套「HTTP 策略」内部走 RPC 时由 status details 表达对外由 BFF/网关归一化。8.5 错误分类业务、系统、基础设施类型type示意可重试用户可见示例业务BUSINESS否是库存不足、格式错误系统SYSTEM有时通常否DB 连接失败基础设施INFRA是可选提示熔断、降级、下游超时熔断/降级归类为INFRA / SYSTEM而非业务错误。宜独立码段例如9001 熔断Circuit Breaker Open 9002 降级Fallback 9003 下游超时8.6 BFF / 网关归一化统一 JSON 字段名与code体系将内部服务名、技术细节转为用户可读message不要把inventory-service panic原文返回给前端9. 中心化错误码治理错误码是API Schema 的一部分不是某个仓库里的私有魔法数字。errors.yaml / Proto 定义CI 校验唯一性区间代码生成 Java Go TSOpenAPI 错误示例error-meta 告警映射各微服务引用常量9.1 元数据示例YAMLversion:1.0domains:common:range:1000-1999codes:-code:1000name:INVALID_PARAMhttp_status:400type:BUSINESSretryable:falsesummary_zh:参数校验失败-code:1001name:UNAUTHORIZEDhttp_status:401type:AUTHretryable:falsesummary_zh:未登录或 Token 过期order:range:30000-30999codes:-code:30001name:STOCK_NOT_ENOUGHhttp_status:200type:BUSINESSretryable:falsesummary_zh:库存不足9.2 治理方式选型规模方式小团队Git YAML MR 评审 CI 生成中大型管理后台 DB定期 export 到 Git约束禁止手写 magic numberCI 扫描硬编码SDK 使用各服务只依赖生成的常量 / SDK禁止用反射、运行时解析message或动态字符串做分支——error-meta 变更会导致逻辑静默失效9.3 版本错误码规范带version服务声明依赖的 spec 版本新增code向后兼容修改语义 / 删除major version bump通知客户端10. 与 OpenAPI、监控联动10.1 OpenAPI在接口responses中声明错误示例而不仅是200responses:200:description:业务成功或业务失败见 codecontent:application/json:schema:$ref:#/components/schemas/ApiEnvelopeexamples:success:value:{code:0,message:ok,data:{}}stock_error:value:{code:30001,message:库存不足,data:null}每个接口文档应列出可能出现的业务错误码及处理建议类似云厂商 OpenAPI 错误码表。10.2 监控与告警导出error-meta.json供 Prometheus / Grafana 使用{30001:{type:BUSINESS,severity:INFO,alert:false},5000:{type:SYSTEM,severity:CRITICAL,alert:true}}指标api_error_total{code30001,serviceorder}业务错误库存不足→ 统计转化率不半夜 PagerDuty系统 / INFRA 错误→ 按阈值告警SLO 视角业务code通常不应计入 SLI如可用性、成功率系统错误码才是 SLO 与**错误预算Error Budget**的主要依据——避免「库存不足」吃掉可用性指标日志与 APM每条错误日志带trace_id、error_code、serviceSpan 标记 ERROR code。11. 业界方案速览没有类似 MySQL 的「统一错误码标准产品」大厂多自研 Registry Schema CI 生成。思路代表特点Schema 生成器自建 YAML CIRustbiz-errorGoerror-framework无运行时依赖最常用管理平台err0、ErrorHubWeb UI i18n SDK 拉取需考虑高可用框架内置斗鱼 JupiterGo、go-zero 示例错误码分段 文档/监控标签大厂闭源参考字节 Protobuf error_code、腾讯多协议 RegistrygRPC/HTTP/Thrift 映射一致团队规模建议≤20 服务Git YAML CI 生成Java/Go/TS多语言 要 UI评估 err0 / ErrorHub已有 gRPC 体系Proto 定义 error details 代码生成12. 反模式反模式后果前端用message字符串匹配i18n/改文案即逻辑 bug同一code多种含义监控与客户端行为混乱下游错误包装成 500排障地狱业务错误触发系统告警库存不足半夜叫醒 oncall各服务私造 1001「未登录」网关映射爆炸响应带堆栈/SQL安全风险反射/动态字符串判断 codeerror-meta 变更后逻辑静默错误13. 落地阶段建议阶段周期示意内容一1–2 周errors.yaml CI 校验 多语言常量生成新接口强制用常量二1–2 月OpenAPI 注入错误示例日志/监控按 BUSINESS/SYSTEM 拆分三持续管理平台、i18n 文案流水线、告警模板、前端 SDK14. 名词速查卡┌────────────────────────────────────────────────────────────┐ │ HTTP 状态码 协议/基础设施body.code 业务语义 │ │ 成功 code0逻辑分支看 code不看 message │ │ traceId 贯穿响应、日志、APM │ │ 微服务不吞 original_codeBFF 归一化对外文案 │ │ 错误码 Schema → CI 生成 → 文档 监控 │ └────────────────────────────────────────────────────────────┘延伸阅读资源链接HTTP 状态码https://developer.mozilla.org/en-US/docs/Web/HTTP/StatusOpenAPI 规范https://spec.openapis.org/OpenTelemetry 追踪https://opentelemetry.io/docs/Google API 错误模型参考https://cloud.google.com/apis/design/errorsgRPC 状态码https://grpc.io/docs/guides/status-codes/一句话好的错误码体系 HTTP 管传输、code 管业务、信封统一、trace 可追溯在微服务里还要不吞语义、中心化治理让文档、代码与监控读同一套定义。