3. 业务错误码设计原则:分层设计、可读性、可扩展性

业务错误码是后端服务与调用方(前端、网关、其他微服务)之间的契约语言。一套设计良好的错误码体系,能显著降低联调成本、提升问题定位效率,并支撑安全合规审计。本节从分层设计、可读性、可扩展性三个核心原则出发,给出可落地的设计规范。

3.1 分层设计:按模块与严重程度划分命名空间

错误码不应是扁平的一维列表,而应具备清晰的层级结构。推荐采用 “服务域 + 模块 + 错误类型 + 序号” 的四段式编码方案,每段用固定位数表示,便于机器解析和人工识别。

段位 位数 示例值 说明
服务域 2 位数字 01 标识业务域,如 01=用户中心、02=订单、03=支付
模块 2 位数字 03 标识域内子模块,如 01=注册、02=登录、03=权限
错误类型 1 位字母 A A=参数校验、B=鉴权、C=资源状态、D=系统异常
序号 3 位数字 001 模块内唯一递增,从 001 开始

完整示例:0103A001 表示“用户中心-权限模块-参数校验错误-具体为缺少角色ID”。

实践建议:在 OpenAPI 规范中,将错误码定义为 pattern: ^\d{2}\d{2}[A-Z]\d{3}$,并在 description 中注明各段位的含义,实现契约即文档。
业务错误码分层设计结构图 业务错误码分层设计结构 服务域 (2位) 01 = 用户中心 模块 (2位) 03 = 权限 错误类型 (1位) A = 参数校验 序号 (3位) 001 = 缺少角色ID 完整错误码示例:0103A001 用户中心 → 权限模块 → 参数校验 → 缺少角色ID 分层设计使错误码具备自解释能力,支持按域、模块、类型进行聚合监控 每段固定位数,便于正则校验与日志解析

3.2 可读性:自解释与国际化

错误码不应只是数字,而应具备 自解释能力。调用方看到错误码时,应能大致判断问题所在,无需频繁查阅文档。可读性设计包含两个层面:

  • 编码可读:错误类型段使用字母(A/B/C/D)而非纯数字,便于记忆;序号段按模块独立递增,避免全局跳号。
  • 消息可读:每个错误码必须绑定 message(面向开发者)和 userMessage(面向终端用户),支持多语言。
推荐响应结构(JSON):
{
  "code": "0103A001",
  "message": "Role ID is required for permission assignment",
  "userMessage": "角色信息不完整,请重新选择角色",
  "traceId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}

其中 message 用于日志和监控,userMessage 直接展示给用户,traceId 用于全链路追踪。

3.3 可扩展性:预留空间与版本兼容

业务系统会持续演进,错误码体系必须具备向前兼容的扩展能力。以下是三条关键策略:

策略 做法 示例
预留段位空间 每个模块的序号段预留 20% 空号,不连续分配 模块 03 的序号从 001~080 分配业务码,081~100 预留
错误类型扩展 字母段保留未定义字母(如 E/F/G),供未来新类型使用 当前用 A/B/C/D,未来可扩展 E=限流、F=数据一致性
版本化兼容 在响应中增加 errorVersion 字段,支持新旧码共存 "errorVersion": "v2",旧客户端仍解析 v1 格式
常见反模式:不要使用 HTTP 状态码直接映射业务错误(如 400 表示“参数错误”,但无法区分“缺少字段”和“格式错误”);不要使用全局递增序号(如 10001、10002),这会导致模块间耦合,且无法按域隔离。
错误码可扩展性设计示意图 错误码可扩展性设计 当前分配区 序号 001 ~ 080(已分配) 错误类型 A/B/C/D(已定义) 预留扩展区 序号 081 ~ 100(预留 20%) 错误类型 E/F/G(未来扩展) 版本化兼容:响应中携带 errorVersion 字段 v1 客户端忽略新字段,v2 客户端解析扩展码 预留空间 + 版本字段 = 无痛升级,避免破坏性变更

3.4 错误码与安全合规的关联

错误码设计直接影响安全审计与合规要求。以下是将安全合规融入错误码体系的要点:

  • 敏感信息脱敏:userMessage 中不得包含用户身份证号、银行卡号、密码等敏感字段;message 中也不应输出数据库连接串、堆栈信息。
  • 审计追踪:每个错误响应必须携带 traceId,便于安全审计系统关联请求链路。
  • 频率限制标识:为限流、熔断等安全场景预留独立错误类型(如 E=限流),避免与普通业务错误混淆。
  • 合规分类:在错误码元数据中增加 complianceCategory 字段,标记该错误是否涉及 GDPR/CCPA/PIPL 等合规要求。
OpenAPI 契约示例:在 components/schemas 中定义统一的错误响应模型,所有接口复用,确保安全合规字段不遗漏。
ErrorResponse:
  type: object
  required: [code, message, traceId]
  properties:
    code:
      type: string
      pattern: '^\d{2}\d{2}[A-Z]\d{3}$'
      description: "业务错误码,如 0103A001"
    message:
      type: string
      description: "面向开发者的技术描述"
    userMessage:
      type: string
      description: "面向终端用户的友好提示"
    traceId:
      type: string
      format: uuid
      description: "全链路追踪ID,用于安全审计"
    errorVersion:
      type: string
      enum: [v1, v2]
      description: "错误码版本,支持向前兼容"
    complianceCategory:
      type: string
      enum: [none, gdpr, ccpa, pipl]
      description: "合规分类标识"

3.5 小结:错误码设计检查清单

在落地错误码体系时,建议对照以下清单进行评审:

  1. 分层:是否包含服务域、模块、错误类型、序号四段?每段位数是否固定?
  2. 可读:错误类型是否使用字母?是否同时提供 message 和 userMessage?
  3. 可扩展:每个模块是否预留了 20% 序号空间?是否定义了未来错误类型字母?
  4. 安全合规:错误消息是否脱敏?是否包含 traceId?是否标记了合规分类?
  5. 契约化:OpenAPI 规范中是否定义了统一的 ErrorResponse schema?所有接口是否复用?

遵循以上原则,错误码将从“临时凑合的字符串”进化为“可治理、可审计、可演进的业务契约”,为后端系统的长期稳定运行奠定基础。