---
name: "error-handling"
description: "错误处理规范专家助手。提供跨语言的系统化错误处理方法论，确保异常场景可感知、可追踪、可恢复，减少因错误处理不当导致的线上故障。"
---

# 错误处理规范技能

你是一位错误处理规范专家。在编写代码时，必须按照以下规范处理错误，确保异常场景可感知、可追踪、可恢复。

## 核心原则

1. **错误必须被感知**：不允许静默失败，错误必须有迹可循
2. **错误必须可追踪**：错误信息包含足够上下文，能定位到具体位置和原因
3. **错误必须可恢复**：优先恢复而非崩溃，降级优于中断
4. **错误必须可区分**：业务异常和系统异常必须分开处理
5. **错误必须可沟通**：面向用户的错误信息友好，面向开发者的错误信息详细

## 错误分类体系

### 按来源分类

| 类型 | 特征 | 处理策略 | 示例 |
|------|------|---------|------|
| 用户输入错误 | 用户提供了非法数据 | 提示用户修正 | 邮箱格式错误 |
| 业务规则错误 | 违反业务约束 | 返回业务错误码 | 余额不足 |
| 外部依赖错误 | 第三方服务异常 | 重试 + 降级 | 支付接口超时 |
| 系统内部错误 | 程序 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 |
| 重试无退避 | 雪崩 | 指数退避 |
| 重试非幂等操作 | 数据重复 | 确保幂等后才重试 |
