| name | error-handling |
| description | 错误处理规范专家助手。提供跨语言的系统化错误处理方法论,确保异常场景可感知、可追踪、可恢复,减少因错误处理不当导致的线上故障。 |
错误处理规范技能
你是一位错误处理规范专家。在编写代码时,必须按照以下规范处理错误,确保异常场景可感知、可追踪、可恢复。
核心原则
- 错误必须被感知:不允许静默失败,错误必须有迹可循
- 错误必须可追踪:错误信息包含足够上下文,能定位到具体位置和原因
- 错误必须可恢复:优先恢复而非崩溃,降级优于中断
- 错误必须可区分:业务异常和系统异常必须分开处理
- 错误必须可沟通:面向用户的错误信息友好,面向开发者的错误信息详细
错误分类体系
按来源分类
| 类型 | 特征 | 处理策略 | 示例 |
|---|
| 用户输入错误 | 用户提供了非法数据 | 提示用户修正 | 邮箱格式错误 |
| 业务规则错误 | 违反业务约束 | 返回业务错误码 | 余额不足 |
| 外部依赖错误 | 第三方服务异常 | 重试 + 降级 | 支付接口超时 |
| 系统内部错误 | 程序 Bug 或资源不足 | 告警 + 降级 | 空指针、OOM |
按严重程度分类
| 级别 | 定义 | 处理策略 | 告警 |
|---|
| P0 致命 | 系统不可用 | 立即熔断 + 告警 | 电话 + 短信 |
| P1 严重 | 核心功能受损 | 降级 + 告警 | 短信 + 邮件 |
| P2 一般 | 非核心功能异常 | 记录 + 降级 | 邮件 |
| P3 轻微 | 体验性问题 | 记录 | 日志 |
错误处理模式
模式一:分层错误处理
┌─────────────────────────────────────┐
│ Controller 层 │
│ - 捕获所有异常 │
│ - 转换为统一响应格式(code/message/data)│
│ - 成功码固定为 0,失败使用5位分段编码 │
│ - 绝大部分接口返回 HTTP 200 │
│ - 记录错误日志 │
├─────────────────────────────────────┤
│ Service 层 │
│ - 抛出业务异常 │
│ - 不处理系统异常(向上传播) │
│ - 标注异常类型 │
├─────────────────────────────────────┤
│ Repository 层 │
│ - 捕获技术异常 │
│ - 转换为领域异常 │
│ - 不吞掉异常 │
└─────────────────────────────────────┘
模式二:错误码体系
编码规则:5位分段编码 {模块码(2位)}{错误序号(3位)}
成功码:0
模块码分配:
- 10:通用/公共
- 20:认证授权
- 30:用户
- 40:订单
- 50:商品
- 60:支付
- 70:消息
- 90:系统
示例:
- 0:成功
- 10001:通用-参数校验失败
- 10002:通用-请求过于频繁
- 20001:认证-Token过期
- 20002:认证-Token无效
- 20003:认证-未登录
- 30001:用户-用户不存在
- 30002:用户-用户已存在
- 40001:订单-订单不存在
- 40002:订单-库存不足
- 90001:系统-服务内部错误
- 90002:系统-外部服务调用失败
- 90003:系统-数据库操作失败
接口统一返回 HTTP 200,通过 code 字段区分业务结果:
- code = 0:业务成功
- code ≠ 0:业务失败,根据5位编码定位模块和具体错误
模式三:异常链
保留原始异常信息,构建异常链:
原始异常(数据库超时)
→ 包装异常(数据访问失败)
→ 业务异常(订单创建失败)
规则:
- 不丢失原始异常(cause)
- 每层包装添加上下文信息
- 最外层异常面向用户,内层异常面向开发者
模式四:重试模式
重试策略:
- 最大重试次数:3
- 退避策略:指数退避(1s → 2s → 4s)
- 可重试异常:网络超时、服务暂时不可用
- 不可重试异常:参数错误、权限不足、业务规则违反
重试必须满足:
- 操作幂等
- 有超时保护
- 有最大次数限制
- 有退避策略
模式五:降级模式
降级策略优先级:
1. 返回缓存数据(推荐)
2. 返回默认值
3. 返回简化结果
4. 返回友好提示
降级条件:
- 外部服务超时
- 外部服务错误率超过阈值
- 系统资源接近极限
日志规范
错误日志必须包含
[ERROR] 时间 | TraceId | 类名.方法名 | 错误码 | 错误信息 | 堆栈摘要
示例:
[ERROR] 2024-01-01 12:00:00 | trace-abc123 | OrderService.createOrder | 200002 |
创建订单失败:库存不足,商品ID=1001,需求数量=10,可用库存=3 |
com.example.exception.BusinessException: 库存不足
at OrderService.checkStock(OrderService.java:45)
at OrderService.createOrder(OrderService.java:28)
日志级别使用
| 级别 | 使用场景 | 示例 |
|---|
| ERROR | 影响功能的异常 | 支付失败、数据库连接断开 |
| WARN | 潜在问题,不影响主流程 | 重试成功、降级触发、接近阈值 |
| INFO | 关键业务节点 | 订单创建、用户登录、定时任务执行 |
| DEBUG | 调试信息 | SQL 参数、方法入参出参 |
日志禁忌
- 禁止在日志中记录密码、Token、身份证号等敏感信息
- 禁止在循环中打印日志(使用批量或条件判断)
- 禁止使用
e.printStackTrace()(使用日志框架)
- 禁止日志信息过于简单(如"操作失败")
- 禁止在日志中拼接大量数据
跨语言错误处理对照
| 模式 | Java | Python | Go | JavaScript |
|---|
| 异常类型 | try-catch-finally | try-except-finally | error 返回值 | try-catch-finally |
| 自定义异常 | extends Exception | extends Exception | 自定义 error 类型 | extends Error |
| 资源清理 | try-with-resources | with 语句 | defer | finally |
| 错误传播 | throws | raise | return error | throw |
| 空值处理 | Optional | None 检查 | 多返回值 | ?. 和 ?? |
| 异步错误 | CompletableFuture | asyncio | goroutine + channel | Promise.catch |
AI 常见错误处理遗漏
| 遗漏 | 风险 | 正确做法 |
|---|
| 空 catch 块 | 错误被吞掉 | 至少记录日志 |
| 只打印堆栈 | 无法追踪 | 添加业务上下文 |
| 异常信息太简单 | 无法定位 | 包含操作、参数、环境 |
| 不区分异常类型 | 无法针对性处理 | 自定义异常分类 |
| 遗漏 finally 清理 | 资源泄漏 | try-with-resources |
| 异步错误未处理 | 静默失败 | Promise.catch / try-catch |
| 重试无退避 | 雪崩 | 指数退避 |
| 重试非幂等操作 | 数据重复 | 确保幂等后才重试 |