Debug Methodology
Systematic approach to debugging and problem-solving. Distilled from real production incidents and industry best practices.
⚠️ The Root Cause Imperative
Every fix MUST target the root cause. Workarounds are forbidden unless explicitly approved.
Before proposing ANY solution, pass the Root Cause Gate:
CODEBLOCK0
The 5 Whys — Mandatory for Non-Obvious Problems
CODEBLOCK1
Common Workaround Traps
| Problem | Workaround (❌) | Root Cause Fix (✅) |
|---|
| API timeout | Switch to faster model | Use streaming / fix the slow query |
| Data precision loss |
Search by name instead of ID | Fix BigInt parsing |
| Search returns nothing | Try different search strategy | Fix the search implementation |
| Dependency conflict | Downgrade / pin version | Use correct environment (venv) |
| Feature doesn't work | Remove the feature | Debug why it fails |
Self-check question: "Am I solving the problem, or avoiding it?"
Phase 1: STOP — Assess Before Acting
Before ANY fix attempt:
CODEBLOCK2
For running services:
CODEBLOCK3
NEVER restart a service without first recording its original startup command.
Phase 2: Hypothesize — Form ONE Theory
Priority order:
- 1. Did I change something? → diff/revert first
- Did the environment change? → versions, deps, configs
- Did external inputs change? → API responses, data formats
- Genuine new bug? → only after ruling out 1-3
Phase 3: Test — One Change at a Time
CODEBLOCK4
Do NOT stack changes.
Phase 4: Patch-Chain Detection
2 fix attempts failed → STOP. Revert ALL. Back to Phase 1.
You are likely:
- - Fixing symptoms of a wrong fix
- In the wrong environment entirely
- Misunderstanding the architecture
Phase 5: Post-Fix Verification
After any fix, verify:
CODEBLOCK5
Anti-Patterns
🚨 Workaround Addiction (NEW — Most Common!)
Bypassing the problem instead of fixing it. "It's slower but works" / "Use a different approach".
→
Ask: "Am I solving or avoiding?" If avoiding → find the real fix.
→ Workarounds are ONLY acceptable when: (1) explicitly approved by user, (2) clearly labeled as temporary, (3) a TODO is created for the real fix.
🚨 Drunk Man Anti-Pattern
Randomly changing things until the problem disappears.
→ Each change needs a hypothesis.
🚨 Streetlight Anti-Pattern
Looking where comfortable, not where the problem is.
→ "Is this where the bug IS, or where I KNOW HOW TO LOOK?"
🚨 Cargo Cult Fix
Copying a fix without understanding why it works.
→ Understand the mechanism first.
🚨 Ignoring the User
User says "it broke after you changed X" → immediately diff X.
→ User observations are the most valuable data.
Environment Checklist
CODEBLOCK6
Deployment Safety (Hardened SCP Flow)
Iron Rule: NEVER edit files directly on the server. NEVER overwrite server files without backup.
CODEBLOCK7
Pull Scope Rules
CODEBLOCK8
What NOT to Do
CODEBLOCK9
🚨 Server Code Modification Rules
Every code change on a server MUST be syntax-verified before restart/reload.
CODEBLOCK10
Why: sed -i multi-line insertion silently corrupts JS (newlines become single line), causing syntax errors that break the entire page with no visible error to the user.
Decision Tree
CODEBLOCK11
调试方法论
系统化的调试与问题解决方法。提炼自真实生产事故与行业最佳实践。
⚠️ 根本原因原则
每个修复方案必须针对根本原因。除非明确批准,否则禁止使用临时解决方案。
在提出任何解决方案之前,必须通过根本原因检查门:
┌─────────────────────────────────────────────┐
│ 根本原因检查门 │
│ │
│ 1. 实际的问题是什么? │
│ 2. 为什么会发生?(不仅仅是发生了什么) │
│ 3. 我的修复方案能消除为什么吗? │
│ 是 → 继续 │
│ 否 → 这是临时方案 → 停止 │
│ │
│ 临时方案测试: │
│ 如果我移除修复方案,bug会重现吗? │
│ 是 → 临时方案(请修复根本原因) │
│ 否 → 真正的修复 ✅ │
└─────────────────────────────────────────────┘
5个为什么——非明显问题必须使用
问题:API返回524超时
为什么?→ Cloudflare切断超过100秒的连接
为什么?→ API调用耗时超过100秒
为什么?→ 使用非流式请求,服务器保持连接静默
为什么?→ 代码使用常规fetch,而非流式
修复:→ 使用流式(服务器持续发送数据,Cloudflare不会切断)
❌ 错误:切换到更快的模型(临时方案——避免超时而非修复问题)
✅ 正确:使用流式API(根本原因——Cloudflare需要持续的数据流)
常见临时方案陷阱
| 问题 | 临时方案(❌) | 根本原因修复(✅) |
|---|
| API超时 | 切换到更快的模型 | 使用流式/修复慢查询 |
| 数据精度丢失 |
按名称而非ID搜索 | 修复BigInt解析 |
| 搜索无结果 | 尝试不同的搜索策略 | 修复搜索实现 |
| 依赖冲突 | 降级/锁定版本 | 使用正确的环境(venv) |
| 功能不工作 | 移除该功能 | 调试失败原因 |
自检问题:我是在解决问题,还是在回避问题?
阶段1:停止——行动前先评估
在任何修复尝试之前:
□ 确切症状是什么?(错误信息、行为、截图)
□ 上次正常工作是什么时候?之后发生了什么变化?
□ 服务是如何运行的?(进程、环境、启动命令)
对于正在运行的服务:
bash
ps -p -o command= # 如何启动的?
ls .venv/ venv/ env/ # 虚拟环境?
which python3 && python3 --version
which node && node --version
切勿在未记录原始启动命令的情况下重启服务。
阶段2:假设——提出一个理论
优先级顺序:
- 1. 我是否修改了什么? → 先执行diff/回滚
- 环境是否发生了变化? → 版本、依赖、配置
- 外部输入是否发生了变化? → API响应、数据格式
- 真正的新bug? → 仅在排除1-3之后
阶段3:测试——一次只做一个更改
更改X → 测试 → 工作?→ 完成
→ 失败?→ 回滚X → 新假设
不要堆叠更改。
阶段4:补丁链检测
2次修复尝试失败 → 停止。回滚所有更改。回到阶段1。
你可能正在:
阶段5:修复后验证
任何修复之后,验证:
□ 是否解决了原始问题?(不仅仅是消除错误)
□ 是否引入了新问题?(回归检查)
□ 移除修复方案是否会让bug重现?(确认因果关系)
□ 修复是否在正确的层级?(不是在上游修补症状)
反模式
🚨 临时方案依赖症(新增——最常见!)
绕过问题而非修复问题。虽然慢但能用/换个方法。
→
问自己:我是在解决还是回避? 如果是回避 → 找到真正的修复方案。
→ 临时方案仅在以下情况下可接受:(1) 经用户明确批准,(2) 明确标记为临时,(3) 创建TODO用于真正的修复。
🚨 醉汉反模式
随机更改直到问题消失。
→ 每次更改都需要一个假设。
🚨 路灯反模式
只在熟悉的地方找问题,而不是问题实际所在。
→ 这是bug所在的位置,还是我知道如何查找的位置?
🚨 盲目模仿修复
复制修复方案却不理解其工作原理。
→ 先理解机制。
🚨 忽视用户
用户说你改了X之后它就坏了 → 立即对X执行diff。
→ 用户的观察是最有价值的数据。
环境检查清单
□ 运行时:系统还是venv/nvm?
□ 依赖:匹配预期版本?
□ 配置:.env、config.json——最近有更改?
□ 进程管理器:PM2/systemd——重启方法?
□ 日志:重现前执行tail -f
□ 备份:任何更改前创建快照
部署安全(强化SCP流程)
铁律:切勿直接在服务器上编辑文件。切勿在无备份的情况下覆盖服务器文件。
标准部署(每次执行,无一例外):
- 1. 拉取 scp server:/opt/apps/项目/ ./local-项目/
(拉取所需文件 + 相关文件)
- 2. 编辑 在本地进行更改
(复杂多行 → 编写完整文件,切勿使用sed)
- 3. 验证 node -c *.js # 语法检查
node -e require(./file) # 模块加载检查
(验证失败则停止——不要继续)
- 4. 备份 ssh server cp file file.bak.$(date +%s)
- 5. 推送 scp ./local-file server:/opt/apps/项目/file
- 6. 重启 pm2 restart
(使用与原始启动相同的方法——先检查ps/pm2 show)
- 7. 健康检查 curl -s http://localhost:/health
pm2 logs
--lines 5 --nostream
(如果不健康 → 立即回滚备份)
拉取范围规则
更改1个文件 → 拉取该文件 + 其导入/导入者
更改路由 → 同时拉取server.js(检查挂载点)
更改前端 → 同时拉取index.html(检查脚本标签)
更改配置 → 同时拉取读取配置的代码
不确定要拉取什么 → 拉取整个项目目录
禁止操作
❌ 在服务器上对多行代码使用sed -i
❌ 编辑.js后跳过node -c
❌ 在语法验证前执行pm2 restart
❌ 在健康检查通过前告诉用户刷新
❌ 无备份推送
🚨 服务器代码修改规则
服务器上的每次代码更改必须在重启/重新加载前进行语法验证。
编辑.js文件后:
□ node -c # 语法检查
□ node -e require(./) # 模块加载检查(针对路由文件)
□ 失败 → 不要重启。不要告诉用户刷新。先修复。
编辑.html文件后:
□ 检查关键标签闭合(div/script/style)
□ grep -c
复杂多行更改:
□ 本地编写完整文件 → scp上传
□ 切勿使用sed进行多行代码插入(换行符会被吞掉)
□ 如果必须使用sed → 立即用node -c验证
重启顺序:
□ node -c *.js通过 → pm2 restart
□ 检查pm2 logs --lines 5查看启动错误
□ curl健康端点确认服务已启动
原因:sed -i多行插入会静默破坏JS(换行符变成单行),导致语法错误,使整个页面崩溃且用户看不到任何可见错误。
决策树
问题出现
├─ 我刚编辑了什么?→ DIFF → 如果可疑则回滚
├─ 服务无法启动?→ 检查启动命令 + 环境
├─ 修复后出现新错误?→ 停止(补丁链!)→ 回滚 → 阶段1
├─ 用户报告回归?→ DIFF前后对比
├─ 想用临时方案?→ 根本原因检查门 → 修复真正问题
└─ 间歇性问题?→ 检查日志 + 外部依赖 + 时间
标签
skill
ai