05 - 调试排错食谱
系统化定位问题根因,从错误信息到修复验证的完整排错流程。
适用场景
| 场景 | 典型信号 | 推荐食谱 |
|---|---|---|
| 线上/本地报错,需快速定位 | 有明确错误信息或堆栈 | 食谱 1:根因定位 |
| Bug 已定位,修复前需防回归 | 已知复现步骤 | 食谱 2:回归测试先行 |
| 修复前需评估波及范围 | 涉及公共模块或 API 变更 | 食谱 3:影响分析 |
| 问题难以复现,缺少可观测性 | 偶发问题、状态不确定 | 食谱 4:日志注入 |
| 功能正确但慢 | 响应时间异常、CPU/内存告警 | 食谱 5:性能瓶颈定位 |
| 安装/构建失败,版本冲突 | npm install 报错、peer dep 警告 | 食谱 6:依赖冲突解决 |
食谱 1:根因定位
场景描述
拿到一个错误信息或堆栈跟踪,需要系统性地定位根因而非头痛医头。适用于运行时异常、构建失败、测试不通过等任何有明确报错的情况。
核心模板
我遇到了以下错误:
## 错误信息
{{错误信息}}
## 上下文
- 语言/框架:{{技术栈}}
- 触发条件:{{复现步骤}}
- 最近变更:{{最近改了什么}}
## 请求
1. 分析错误信息,解释每一层堆栈的含义
2. 列出最可能的 3 个根因,按概率排序
3. 给出每个假设的验证方法
4. 确认根因后,给出最小修复方案
5. 提供防御措施,防止类似问题再次发生变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{错误信息}} | 完整的错误信息和堆栈跟踪 | TypeError: Cannot read properties of undefined (reading 'map') |
{{技术栈}} | 项目使用的语言和框架 | React 18 + TypeScript + Vite |
{{复现步骤}} | 触发错误的操作序列 | 登录后点击"我的订单"页面 |
{{最近变更}} | 出错前的代码改动 | 重构了 useAuth hook,拆分为多个子 hook |
好坏对比
❌ 模糊描述:
我的代码报错了,Cannot read properties of undefined,帮我修一下。
✅ 结构化报错:
我遇到了以下错误:
TypeError: Cannot read properties of undefined (reading 'map')出现在OrderList.tsx:42。React 18 + TypeScript 项目,在登录后点击"我的订单"页面时触发。昨天重构了 useAuth hook,拆分为多个子 hook。请分析根因并给出修复方案。
实战案例
## 错误信息
TypeError: Cannot read properties of undefined (reading 'map')
at OrderList (OrderList.tsx:42:28)
at renderWithHooks (react-dom.development.js:16305)
## 上下文
- 语言/框架:React 18 + TypeScript 5 + Vite 5
- 触发条件:登录后点击侧边栏"我的订单",页面白屏
- 最近变更:将 useAuth() 拆分为 useAuth() + useUser(),
OrderList 原来从 useAuth 取 user.orders,现在需要从 useUser 取
## 请求
(同核心模板 5 步)Claude 增强 💡
- 使用
/debugSkill 自动执行根因定位流程,它会沿调用链追踪并检查近期 git 变更 - 用
@OrderList.tsx引用出错文件,让 Claude 直接看到源码上下文 - 粘贴完整堆栈而非截图,Claude 可以解析每一帧的文件路径和行号
- 追问
git log --oneline -5 -- src/hooks/useAuth.ts的输出,帮助定位引入 Bug 的 commit
食谱 2:回归测试先行
场景描述
在修复 Bug 之前,先写一个能复现该 Bug 的失败测试用例。修复后测试应通过,且未来不会回归。这是 TDD 在 Bug 修复场景的经典应用。
核心模板
我在修复一个 Bug,需要先写回归测试。
## Bug 描述
{{Bug描述}}
## 复现条件
- 输入:{{触发输入}}
- 期望行为:{{正确行为}}
- 实际行为:{{错误行为}}
## 相关代码
文件:{{文件路径}}
当前测试文件:{{测试文件路径}}
## 请求
1. 写一个精确复现该 Bug 的测试用例(应当 FAIL)
2. 测试名称要描述 Bug 场景,而非实现细节
3. 覆盖相关边界条件(至少 2 个额外用例)
4. 确认测试 FAIL 后,再给出最小修复代码
5. 修复后确认所有测试 PASS变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{Bug描述}} | Bug 的一句话概括 | 价格计算在折扣为 0% 时返回 NaN |
{{触发输入}} | 引发 Bug 的具体输入 | discount = 0, price = 99.9 |
{{正确行为}} | 期望的返回值或行为 | 返回 99.9(原价) |
{{错误行为}} | 实际的返回值或行为 | 返回 NaN |
{{文件路径}} | Bug 所在源码文件 | src/utils/pricing.ts |
{{测试文件路径}} | 对应的测试文件 | src/utils/__tests__/pricing.test.ts |
好坏对比
❌ 直接修复不写测试:
pricing.ts里calculateDiscount函数有 Bug,当 discount 为 0 时结果是 NaN,帮我修一下。
✅ 测试先行再修复:
pricing.ts的calculateDiscount(99.9, 0)返回 NaN 而非 99.9。请先在pricing.test.ts写一个覆盖 discount=0 场景的失败测试,确认 FAIL 后再修复,最终所有测试应 PASS。
实战案例
## Bug 描述
calculateDiscount 在折扣为 0 时返回 NaN,而非原价。
## 复现条件
- 输入:price = 99.9, discountPercent = 0
- 期望:返回 99.9 | 实际:返回 NaN
## 相关代码
文件:src/utils/pricing.ts | 测试:src/utils/__tests__/pricing.test.ts
## 请求
(同核心模板 5 步)Claude 增强 💡
- 用
@pricing.ts和@pricing.test.ts引用源码和测试文件,Claude 可以直接阅读现有测试风格 - Claude Code 可以直接运行
npm test -- --watch实时验证测试状态 - 让 Claude 先
git stash当前修改,确认测试确实在未修复状态下 FAIL
食谱 3:影响分析
场景描述
修复 Bug 或变更代码之前,先评估改动的"爆炸半径"。哪些模块会受影响?有没有测试覆盖?应该按什么顺序改?避免修了一个 Bug 引入三个新 Bug。
核心模板
我准备修改以下代码,请先做影响分析:
## 要修改的内容
- 文件:{{目标文件}}
- 改动内容:{{改动描述}}
## 项目上下文
- 技术栈:{{技术栈}}
- 模块关系:{{模块依赖说明}}
## 请分析
1. **直接影响**:哪些文件直接 import 或调用了这个模块?
2. **间接影响**:直接影响的文件又被谁依赖?(追踪两层)
3. **测试覆盖**:受影响模块的测试覆盖情况,标注无测试的模块
4. **风险评估**:每个受影响点的风险等级(高/中/低)
5. **建议改动顺序**:可逐步验证的修改步骤变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{目标文件}} | 准备修改的文件路径 | src/services/auth.service.ts |
{{改动描述}} | 具体要改什么 | 将 JWT 过期时间从 token 内读取改为从配置中心读取 |
{{技术栈}} | 项目技术栈 | NestJS + Prisma + PostgreSQL |
{{模块依赖说明}} | 已知的模块关系 | auth.service 被所有需要鉴权的 Controller 使用 |
好坏对比
❌ 改完再看影响:
我把 auth.service.ts 里的 JWT 验证逻辑改了,帮我看看还有没有其他地方要改。
✅ 改前做影响分析:
我准备修改 auth.service.ts 的 JWT 过期时间读取方式,从 token 内读取改为配置中心读取。这个项目是 NestJS + Prisma,auth.service 被所有鉴权 Controller 使用。请先做影响分析,列出所有受影响文件和建议的改动顺序。
实战案例
## 要修改的内容
- 文件:src/services/auth.service.ts
- 改动:validateToken() 过期判断从 JWT exp 字段改为配置中心 TOKEN_TTL
## 项目上下文
- 技术栈:NestJS 10 + Prisma 5 + PostgreSQL 15
- 模块关系:auth.service → AuthGuard → 约 15 个 Controller
## 请分析
(同核心模板 5 步)Claude 增强 💡
- 使用
/impact auth.service.tsSkill 自动搜索所有引用点,生成影响分析报告 - Claude Code 会用 Grep 搜索
import.*auth.service、validateToken等调用链 - 让 Claude 输出 Mermaid 依赖图,直观展示影响传导路径
食谱 4:日志注入
场景描述
问题难以复现或缺少可观测性时,通过策略性注入日志来追踪执行路径和状态变化。适用于偶发 Bug、异步竞态、数据流追踪等场景。
核心模板
我需要在代码中注入诊断日志来追踪一个问题。
## 问题描述
{{问题描述}}
## 怀疑的代码路径
- 入口:{{入口函数}}
- 中间环节:{{中间函数列表}}
- 出口:{{最终输出点}}
## 已知信息
- 问题频率:{{偶发/必现}}
- 环境:{{开发/测试/生产}}
## 请求
1. 在关键位置注入结构化日志(JSON 格式,含 timestamp 和 traceId)
2. 记录入参、出参和关键中间状态
3. 对异步操作记录开始/结束/耗时
4. 日志必须可通过环境变量开关控制(DEBUG=true)
5. 给出日志产出后的分析思路变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{问题描述}} | 需要追踪的问题 | 用户偶尔反馈支付成功但订单状态未更新 |
{{入口函数}} | 数据流的起点 | PaymentWebhookController.handleCallback() |
{{中间函数列表}} | 数据经过的处理节点 | PaymentService.verify() → OrderService.updateStatus() |
{{最终输出点}} | 数据流终点 | 数据库 orders 表 status 字段更新 |
{{偶发/必现}} | 问题复现频率 | 约 2% 的支付回调出现此问题 |
{{开发/测试/生产}} | 出问题的环境 | 生产环境 |
好坏对比
❌ 到处 console.log:
帮我在 PaymentService 的每一行加上 console.log,我看看哪里出了问题。
✅ 策略性结构化日志:
支付回调有 2% 概率订单状态未更新。怀疑路径是 WebhookController → PaymentService.verify → OrderService.updateStatus。请在这条路径的关键节点注入结构化日志,记录 traceId、入参、出参和耗时,日志用 DEBUG 环境变量控制开关。
实战案例
## 问题描述
约 2% 的支付回调,支付成功但 orders.status 仍为 pending。无报错日志。
## 怀疑的代码路径
- 入口:PaymentWebhookController.handleCallback(req)
- 中间:PaymentService.verifySignature() → processPayment() → OrderService.updateStatus()
- 出口:数据库 orders.status 字段
## 已知信息
- 问题频率:约 2%,无法本地复现
- 环境:生产环境(Node.js 20 + NestJS + Prisma + PostgreSQL)
## 请求
(同核心模板 5 步)Claude 增强 💡
- 用
@PaymentWebhookController.ts@PaymentService.ts@OrderService.ts引用调用链源码 - 让 Claude 生成可复制粘贴的日志代码片段和配套的
jq过滤命令 - 日志注入后可用
/debugSkill 对日志输出进行根因分析
食谱 5:性能瓶颈定位
场景描述
功能正确但性能不达标。需要系统性地识别瓶颈点,而非凭直觉优化。适用于接口响应慢、页面加载慢、内存占用高等场景。
核心模板
我需要定位以下性能问题的瓶颈:
## 性能问题
{{问题描述}}
## 度量数据
- 当前指标:{{当前性能数据}}
- 目标指标:{{期望性能数据}}
- 数据来源:{{监控工具/手动测量}}
## 相关代码
- 入口:{{入口路径}}
- 可疑热点:{{怀疑慢的地方}}
## 请求
1. 分析代码,列出所有可能的性能瓶颈点
2. 按影响程度排序(IO > 计算 > 渲染)
3. 对每个瓶颈点给出验证方法(如何确认它确实是瓶颈)
4. 给出优化方案和预期收益
5. 标注优化的风险和权衡(如可读性、缓存一致性等)变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{问题描述}} | 性能问题概述 | 订单列表页接口 P95 响应时间 3.2s |
{{当前性能数据}} | 当前的性能度量值 | P50=800ms, P95=3200ms, P99=5100ms |
{{期望性能数据}} | 目标性能指标 | P95 < 500ms |
{{监控工具/手动测量}} | 数据来源 | Datadog APM |
{{入口路径}} | 慢操作的入口 | GET /api/orders?page=1&size=20 |
{{怀疑慢的地方}} | 初步怀疑的热点 | 可能是数据库查询没命中索引 |
好坏对比
❌ 没有数据的优化请求:
我们的订单列表页很慢,帮我优化一下代码。
✅ 带度量数据的定位请求:
订单列表接口 GET /api/orders P95 响应 3.2s,目标 < 500ms。Datadog 显示数据库查询占了 2.8s。请分析 OrderService.findAll() 及其 Prisma 查询,定位瓶颈并给出优化方案。
实战案例
## 性能问题
订单列表接口数据量超过 10 万条后响应急剧上升。
## 度量数据
- 当前:P50=800ms, P95=3200ms | 目标:P95 < 500ms
- 来源:Datadog APM,DB 查询占 87%
## 相关代码
- 入口:GET /api/orders → OrderController.findAll()
- 可疑热点:Prisma 查询含 3 个 JOIN + 1 个子查询,无分页游标
## 请求
(同核心模板 5 步)Claude 增强 💡
- 用
@OrderService.ts和@schema.prisma引用源码,Claude 可分析 N+1 问题和索引定义 - 让 Claude 生成
EXPLAIN ANALYZESQL,粘贴执行计划后继续分析 - 要求输出对比表格:
改动 | 预期收益 | 风险 | 复杂度
食谱 6:依赖冲突解决
场景描述
npm install 失败、peer dependency 警告、运行时因版本不兼容报错。需要理清依赖树,找到冲突根源,给出兼容的版本方案。
核心模板
我遇到了依赖冲突问题,需要帮助解决。
## 错误信息
{{安装或运行时报错}}
## 当前环境
- 包管理器:{{npm/yarn/pnpm}} {{版本}}
- Node.js:{{版本}}
- 项目类型:{{monorepo/单仓库}}
## 冲突上下文
- 我在安装/升级:{{要安装的包}}
- 已有依赖中的冲突方:{{冲突的现有依赖}}
## 请求
1. 解析错误信息,画出冲突的依赖关系
2. 找到冲突的根本原因(哪两个包要求了不兼容的版本)
3. 给出至少 2 种解决方案,标注各自的优缺点
4. 推荐最佳方案并给出具体的操作步骤
5. 给出验证方法,确认冲突已解决变量说明
| 变量 | 说明 | 示例 |
|---|---|---|
{{安装或运行时报错}} | npm/yarn 报错信息 | ERESOLVE unable to resolve dependency tree |
{{npm/yarn/pnpm}} | 使用的包管理器 | npm |
{{版本}} | 包管理器和 Node.js 版本 | npm 10.2, Node.js 20.11 |
{{monorepo/单仓库}} | 项目结构 | pnpm workspace monorepo |
{{要安装的包}} | 触发冲突的包 | @tanstack/react-query@5 |
{{冲突的现有依赖}} | 与之冲突的现有包 | react@17(项目还未升级到 React 18) |
好坏对比
❌ 粘贴报错不给上下文:
npm install 报错了:ERESOLVE unable to resolve dependency tree。怎么修?
✅ 带上下文的冲突排查:
我在 React 17 项目中安装 @tanstack/react-query@5 时遇到 ERESOLVE 错误。项目用 npm 10.2 + Node 20。react-query@5 要求 react@18,但项目还在 17。请分析依赖关系,给出不升级 React 的兼容方案和升级 React 的完整方案。
实战案例
## 错误信息
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR! Found: react@17.0.2
npm ERR! peer react@"^18.0.0" from @tanstack/react-query@5.17.0
## 当前环境
- 包管理器:npm 10.2.0 | Node.js:v20.11.0
- 项目类型:单仓库(CRA 迁移到 Vite 中途)
## 冲突上下文
- 安装:@tanstack/react-query@5
- 冲突方:react@17.0.2(未升级到 React 18)
## 请求
(同核心模板 5 步)Claude 增强 💡
- 用
@package.json引用依赖声明,让 Claude 运行npm ls react查看实际依赖解析 - 对于 monorepo,用
@pnpm-workspace.yaml引用工作区配置 - Claude 可以直接执行
npm install --legacy-peer-deps并验证运行时兼容性
组合技巧
组合 1:根因定位 + 回归测试 + 影响分析(标准 Bug 修复流)
食谱 1 定位根因 → 食谱 3 评估影响范围 → 食谱 2 写回归测试并修复。
1. 先执行根因定位,确认 Bug 原因
2. 对修复方案做影响分析,确保不会引入新问题
3. 写回归测试 → 确认 FAIL → 修复 → 确认 PASS组合 2:日志注入 + 根因定位(偶发 Bug 排查流)
先用食谱 4 注入日志收集数据,拿到日志后用食谱 1 分析根因。
1. 用食谱 4 注入结构化日志,部署到出问题的环境
2. 等待问题复现,收集日志
3. 将日志输出粘贴给 Claude,用食谱 1 的框架分析根因组合 3:性能瓶颈 + 影响分析(性能优化流)
食谱 5 定位瓶颈 → 食谱 3 评估优化改动影响 → 逐步优化并验证。
1. 用食谱 5 定位性能瓶颈,确定优化方案
2. 用食谱 3 对优化方案做影响分析
3. 按建议顺序逐步优化,每步验证相关资源
- doc-15 SS3.5 调试修复 — 提示词理论基础与调试场景速查
- /debug Skill — 系统性问题诊断自动化流程
- /impact Skill — 改动影响分析自动化流程
- 04-代码审查食谱 — 审查阶段的提示词模板
- 06-重构优化食谱 — 重构阶段的提示词模板