第 10 章

AI 智能 Debug——5类错误的精准定位方法与提问模板

第10章:AI 智能 Debug——5类错误的精准定位方法与提问模板

用 Cursor Chat 高效 Debug 的关键是「喂对信息」。本章按 5 类常见错误分类,给出每类错误的 AI Debug 最佳提问模板,以及如何用 AI 分析日志、定位性能问题。读完本章,你将掌握把任意错误转化为精准 AI 提问的标准方法。

为什么 AI Debug 有时没用

AI Debug 失败的最常见原因只有一个:给的信息不够具体。

无效提问:
"这个函数有 bug,帮我找一下"

有效提问:
错误类型 + 完整 stack trace + 触发条件 + 期望行为 + 已排查内容

把 Debug 提问想象成给医生描述症状:说"我不舒服"没法诊断,说"昨天吃完饭后右下腹开始间歇性疼痛,按压时加重"才能判断。AI 见过海量错误模式,但它对你的运行时状态一无所知——你需要把运行时信息翻译成文字传递给它。

最常见的错误:截断 stack trace。 Stack trace 里的每一行都是信息,特别是中间调用层。只给 AI 最后一行错误信息,等于只给医生看症状,不给病历。永远粘贴完整的 stack trace。

5 类错误的 Debug 模板

类型 1:运行时异常(TypeError / AttributeError / NullPointerException)

这类错误最关键的上下文是:触发路径 + 数据状态 + 已做的空值检查。

Cursor Chat Prompt 模板

@src/services/order.ts

错误信息(完整 stack trace):
TypeError: Cannot read properties of undefined (reading 'id')
  at OrderService.processOrder (/src/services/order.ts:45:23)
  at POST /api/orders (/src/routes/orders.ts:12:18)

触发条件:
用户下单时,如果购物车为空会触发这个错误

数据上下文:
user 对象结构:{ id: 1, cartId: null }
cart 为 null 时没有做空值检查

期望行为:
cart 为空时返回 400 错误 { error: "Cart is empty" },不应该崩溃

已排查:
- 确认 cartId 为 null 时触发
- processOrder 函数在调用前没有检查 cart 是否存在

类型 2:异步问题(Race condition / Promise 未处理 / async/await 误用)

异步问题的难点是不稳定复现。给 AI 的关键信息是:复现概率、时间关联性、怀疑的并发代码段。

Cursor Chat Prompt 模板

@src/hooks/useCartSync.ts @src/api/cart.ts

问题描述:
有时候用户看到旧数据,刷新后才变成新数据
不稳定复现,大约 20% 的概率发生,高并发时更频繁

相关代码区域:
[引用文件里可疑的并发代码段]

怀疑是 race condition,但不确定在哪里

请分析这段代码中可能的竞态条件,
说明哪些地方没有正确处理异步顺序,
以及如何用锁或队列解决

类型 3:性能问题(慢查询 / 内存泄漏 / 高 CPU)

性能 Debug 必须附上测量数据,而不是感觉。给 AI EXPLAIN ANALYZE 输出、profile 结果、数据规模,它能给出精确的优化方向。

Cursor Chat Prompt 模板

页面加载时间从 200ms 降级到 3s,发生时间:上周五部署后

@src/db/queries/orderQuery.ts

这是相关的数据库查询代码

EXPLAIN ANALYZE 输出:
Seq Scan on orders  (cost=0.00..45231.00 rows=892 width=284)
                    (actual time=0.043..2847.123 rows=892 loops=1)
  Filter: ((status = 'PENDING') AND (created_at >= '2024-01-01'))
  Rows Removed by Filter: 498108

数据规模:users 表 50 万条,orders 表 200 万条

请分析查询性能问题,指出缺少的索引,给出 CREATE INDEX 语句和预期提升效果

AI 会从 Seq ScanRows Removed by Filter: 498108 数据中立即识别出全表扫描,诊断出需要 (status, created_at DESC) 复合索引,并给出预期从 3s 降至 10-50ms 的理由。

类型 4:环境差异(本地好用,线上报错)

环境差异 Debug 的核心是系统性列举两边的差异。Node 版本、数据库类型、环境变量——每个都可能是原因。

Cursor Chat Prompt 模板

本地正常,生产环境报错

错误(生产环境 error log):
[粘贴生产环境错误]

本地:运行正常,无报错

已检查的差异:
- 环境变量:已确认 .env.production 里的值与本地一致
- Node 版本:本地 20.x,生产 18.x(这可能是原因?)
- 数据库:本地 SQLite,生产 PostgreSQL(JSON 字段处理方式不同)
- 文件权限:生产容器里的写权限可能受限

请分析可能的根本原因,按概率从高到低排列,
每种原因给出验证方法

类型 5:逻辑错误(输出结果不符合预期)

逻辑错误最有效的提问方式是给具体的输入-输出对比,而不是描述"感觉不对"。

Cursor Chat Prompt 模板

@src/utils/shipping.ts

函数:calculateShippingCost

测试用例(期望 vs 实际):
- 输入:weight=2, distance=100, memberLevel="gold"
  期望:$5.00(金会员享受 5 折)
  实际:$10.00(折扣没有被应用)

- 输入:weight=5, distance=500, memberLevel="basic"
  期望:$25.00
  实际:$25.00 (这个正确)

- 输入:weight=2, distance=100, memberLevel="silver"
  期望:$7.00(银会员 7 折)
  实际:$10.00(折扣也没有被应用)

规律:basic 级别正确,gold 和 silver 的折扣都没有生效
请找出折扣逻辑的 bug

进阶:用 AI 分析大量日志

生产环境的 bug 往往只能通过日志定位。把日志直接喂给 AI 做模式识别,比人工阅读效率高 10 倍。

日志分析 Prompt

以下是过去 1 小时的应用错误日志(已脱敏),用户反映支付功能偶发失败:

[2024-03-15 14:23:11] ERROR payment_service: Stripe API timeout after 30000ms
[2024-03-15 14:23:45] INFO  payment_service: Payment completed successfully
[2024-03-15 14:31:22] ERROR payment_service: Stripe API timeout after 30000ms
[2024-03-15 14:31:58] ERROR payment_service: Duplicate payment detected, idempotency key already used
[2024-03-15 14:45:03] ERROR payment_service: Stripe API timeout after 30000ms
[2024-03-15 14:45:38] ERROR payment_service: Duplicate payment detected, idempotency key already used
... (类似模式重复 12 次)

请分析:
1. 错误发生的规律是什么?
2. 根本原因是什么?
3. 为什么会产生重复扣款?
4. 如何修复?

AI 会识别出规律:每次 Stripe timeout 之后紧跟着一条 "Duplicate payment detected"。根本原因是超时重试逻辑没有复用同一个 idempotency key,导致 Stripe 收到两次不同 key 的请求,把第二次当作新支付处理,造成重复扣款。修复方案:重试时必须传递和原始请求相同的 idempotency key。

性能 Debug 专题:Profile 数据喂给 AI

对于性能 bug,profile 数据比 stack trace 更有价值。

Python cProfile 分析

import cProfile
import pstats

# 生成 profile 数据
profiler = cProfile.Profile()
profiler.enable()
generate_monthly_report()  # 替换为你的慢函数
profiler.disable()

# 输出可读格式
stats = pstats.Stats(profiler)
stats.sort_stats('cumulative')
stats.print_stats(20)  # 只看 top 20 耗时调用
Prompt:把 pstats 输出喂给 AI

@src/services/report_service.py

以下是 cProfile 对 generate_monthly_report 函数的分析结果(总耗时 12.3 秒):

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1      0.001    0.001   12.298   12.298  report_service.py:45(generate_monthly_report)
  8934      8.234    0.001    8.234    0.001  order_repository.py:78(get_order_by_id)
     1      2.145    2.145    2.145    2.145  db_session.py:34(execute)

问题:get_order_by_id 被调用了 8934 次,总耗时占 67%

请分析这是什么性能问题,给出修复方案和修复后的伪代码

AI 会立即识别出 N+1 查询:先查了 8934 个订单 ID 列表,然后对每个 ID 单独查询详情。修复方向:用 WHERE id IN (...) 批量查询替代逐条查询,预期把 8934 次查询压缩到 1 次。

Node.js Heap Snapshot 分析

步骤

1. 启动时加 --inspect:node --inspect src/server.js
2. 在 Chrome 打开 chrome://inspect,进入 Memory 面板
3. 在内存增长前后各拍一次 Heap Snapshot
4. 对比两次快照,找出 Delta 最大的对象类型
5. 把增长最多的对象名称和 retainer path 粘贴给 AI:

"堆快照对比(间隔 10 分钟):
- EventEmitter 实例:从 142 增长到 4,891
- WebSocketConnection 对象增长了 4,749 个
- Retainer path:WebSocketManager → Map (connections) → WebSocketConnection[]

@src/services/websocket.ts

请分析可能的内存泄漏原因,重点看连接断开时是否有正确的清理逻辑"

本章 5 要点

要点 核心原则
1. 信息完整性 永远附完整 stack trace + 触发条件 + 已排查内容,不能只给错误信息
2. 按类型提问 5 类错误有不同的关键上下文:异步问题给时序、性能问题给 profile 数据、逻辑错误给输入输出对比
3. 数据说话 性能 Debug 必须附测量数据(EXPLAIN、profile 输出),感觉"慢"没有诊断价值
4. 日志模式识别 把 100 行错误日志喂给 AI,让它找规律,比人工阅读快 10 倍
5. 环境差异系统化 本地/线上差异要系统列举:Node 版本、数据库类型、环境变量、文件权限,每个都可能是根本原因
本章评分
4.5  / 5  (31 评分)

💬 留言讨论