mcpField
E
error-debugging

error-debugging

github.com/jablonkai开发445 次安装今天更新
代码仓库

关于 error-debugging

error-debugging 是面向开发者的错误诊断技能,可从崩溃报告、堆栈跟踪和日志中定位根因并提出修复与验证步骤。它强调先识别平台、必要时符号化,再以代码和证据核实假设。

主要功能

  1. 01跨平台错误分析
  2. 02识别并定位失败帧
  3. 03混淆堆栈符号化
  4. 04追溯并验证根因
  5. 05提出修复并运行验证

适用场景

  1. 01解释崩溃报告或错误日志
  2. 02诊断测试、构建或运行时失败
  3. 03分析发布版混淆堆栈
  4. 04按请求修复并验证错误

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jablonkai/skills --skill error-debugging

安装后在 Claude Code 中输入/error-debugging确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
flutter-dart.md
kotlin-android-kmp.md
other-languages.md
rust-cpp.md
swift-apple.md
symbolication.md
worked-examples.md

详细介绍

错误调试

目的

将错误消息转化为解释和修复方案。输入可以是用户手头的任何内容——堆栈跟踪、崩溃报告、panic、日志摘录,有时只有一段截图描述。输出包括:实际失败的代码行、失败原因、需要修改的内容,以及如何确认修改有效。

大部分价值都在中间这一步。抛出异常的栈帧很少就是出错的栈帧——渲染例程中的 NullPointerException 通常意味着上游代码传入了一个本不该为空的值。报告原因,而不是症状。

适用场景

  • 用户粘贴了堆栈跟踪、崩溃报告、panic、ANR 或错误日志——无论是否附带问题
  • 用户询问错误的含义、应用崩溃的原因,或故障的来源
  • 发布版本的跟踪信息需要反混淆或符号化后才能读取
  • 测试失败、构建失败或运行时日志需要进行根因分析

不适用于此技能:

  • 没有具体故障,需要排查整个项目的问题 → code-analyzer
  • 尚未获取失败运行记录的 GitHub Actions 运行 → github-fix-ci-error(该技能会获取运行记录;如果其日志需要深入分析跟踪信息,再回到这里)

前提条件

开始分析前,先确定两件事。

1. 这由哪个平台生成? 根据跟踪信息的特征判断,而不是根据用户的描述——描述经常不准确,也可能缺失:

跟踪信息中的特征平台参考资料
at com.foo.Bar.baz(Bar.kt:42)、Caused by:、FATAL EXCEPTIONKotlin / Java / Androidkotlin-android-kmp.md
ANR in、Input dispatching timed out、"main" prio=5 tid=1 线程转储Android ANRkotlin-android-kmp.md
kfun:、Uncaught Kotlin exception、kotlin.Throwable、ObjCExceptionKotlin/Native(iOS 上的 KMP)kotlin-android-kmp.md
androidx.compose.*、Snapshot、“recomposition”、Composer 栈帧Compose / CMPkotlin-android-kmp.md
FlutterError、RenderFlex、package:flutter/src/...、<asynchronous suspension>Flutter / Dartflutter-dart.md
Exception Type: EXC_BAD_ACCESS、Thread 0 Crashed:、.ips、libswiftCore.dylibSwift / Appleswift-apple.md
thread 'main' panicked at、note: run with RUST_BACKTRACE=1、core::panickingRustrust-cpp.md
SIGSEGV、AddressSanitizer:、#0 0x...、ndk-stack、核心转储C / C++ / NDKrust-cpp.md
Traceback (most recent call last)、at Object.<anonymous>、goroutine 1 [running]Python / JS / Goother-languages.md

加载与平台匹配的那份参考资料。全部加载会浪费上下文,还会混入不适用的惯用做法。例外情况是跟踪信息跨越平台边界——例如,Kotlin/Native 异常导致 iOS 应用终止、携带原生跟踪信息的 Flutter PlatformException,或 JNI 崩溃——此时也需要加载另一侧的参考资料。

2. 跟踪信息是否可读,还是需要先进行符号化?

十六进制地址、单字母类名(a.b.c)、<optimized out> 或缺少行号,都意味着跟踪信息已混淆或尚未符号化。直接分析会得出看似肯定、实则荒谬的结论。请先进行符号化——有关 R8 映射文件、dSYM、flutter symbolize、ndk-stack 和 addr2line,请参阅 symbolication.md。

如果缺少所需的制品(映射文件、dSYM、调试版本),请明确说明,提取仍然有效的信息(异常类型、线程状态、顶层模块),并告知用户需要提供哪些内容,才能进行真正的诊断。

工作流

步骤 1:获取完整错误信息

获取完整的调用栈,而不只是前 3 行。具体请确保包含:

  • 异常类型和消息原文
  • 完整的栈帧列表,包括每个 Caused by: / suppressed / 嵌套链
  • 出错时所在的线程(主线程/UI 线程上的故障与后台线程上的故障,成因不同)
  • 上下文:调试版还是发布版构建、设备/OS、问题是可复现还是偶发、何时开始出现

如果用户粘贴的调用栈被截断,请索取其余部分——关键栈帧通常就在中间部分。如果错误记录在文件中,请直接读取文件,而不是让用户粘贴:

# Keep log reading cheap — grep for the failure region instead of loading whole files
grep -n -A 40 -iE 'exception|fatal|panic|error|traceback' <logfile> | head -120

对于 Android,请直接提取调用栈:

adb logcat -d -b crash | tail -100
步骤 2:按需进行符号化或反混淆

仅当「先决条件 2」指出需要时才进行。请参阅 symbolication.md。 不要跳过这一步,直接分析无法阅读的调用栈——根据混淆后的栈帧得出的每个结论,都只是伪装成答案的猜测。

步骤 3:定位出错的栈帧

不同平台的栈帧顺序各不相同:JVM、Swift、Rust、Go、JS 和原生调用栈会将抛出异常的栈帧列在最前面;Python 则列在最后面。先确认顺序,再回答:

  • 异常在哪里抛出? 找出最接近抛出位置、且属于用户自身代码的栈帧,而不是紧挨着它的框架栈帧。框架栈帧说明了机制;你自己的栈帧说明了错误所在。
  • 最深层的 Caused by: 是什么? 在异常链中,最后一个原因通常才是真正原因;外层包装异常只是传递异常。
  • 哪些栈帧属于该项目? 根据应用的包/模块前缀筛选,其余内容都只是上下文。

然后打开该行的实际源代码。只要能查看代码,就绝不要只根据调用栈进行诊断:

# read the failing site plus the surrounding context
grep -n "<symbol>" -r <src-dir>

如果有 Serena、LSP 等支持符号的工具,请用它们查看所在函数及其调用方,而不是通读整个文件。

如果无法获取源代码(例如来自第三方应用的调用栈,或没有代码仓库的代码片段),请一开始就说明这一点,并将所有依赖未查看代码的结论标记为可能或推测。

步骤 4:追溯根本原因

从出错行反向追查,找出错误状态的来源。对于每个候选原因,你都必须能指出导致故障的具体值或条件。

无论平台是什么,都要考虑以下跨领域原因:

  • 空值/缺失值——可选值被强制解包、可空值被解引用、假设映射查询一定有结果
  • 生命周期/销毁后使用——对象被捕获时有效,但使用时已无效
  • 并发——竞态、撕裂读取、未同步的修改、死锁、在错误线程上执行工作
  • 违反约定——API 调用顺序错误、状态不符,或未在要求的线程/执行者上调用
  • 资源耗尽——OOM、文件描述符耗尽、缓存或集合无界增长
  • 边界不匹配——序列化、FFI、平台通道、JNI:两侧的数据形态不同

平台特定的问题模式目录(被吞掉的 CancellationException、构建期间调用 setState、主执行者违规、RefCell 重复借用、释放后使用等)位于先决条件中加载的平台参考资料。

请区分以下两者,并明确指出属于哪一种:

  • 直接原因——抛出异常的操作(对只有 2 个元素的列表访问 list[3])
  • 根本原因——状态出错的原因(API 返回的项目数少于调用方的假设,且没有任何校验)

仅在直接原因处修复,通常只是转移错误,而不是真正修复。若你将此类修复作为权宜之计提出,请明确说明。

第 5 步:修复前验证假设

将假设表述为可证伪的结论,然后进行测试。先从成本最低的测试开始:

  • 带着假设重新阅读代码路径——跟踪中的每一帧都符合吗?
  • 检查同一区域的近期历史记录:git log -p -L <start>,<end>:<file> | head -80,或 git log --oneline -- <file>
  • 在疑似起因处添加临时断言或日志,然后重现问题
  • 编写一个能重现崩溃的失败测试——这是最佳结果,因为修复后它可以作为回归防护

如果跟踪内容不能完全符合假设,那么假设就是错的。请明确说明并继续调查, 不要据此提交一个看似合理的解释。

第 6 步:提出修复方案

按以下格式简明、有序、易于浏览地给出分析:

## What failed
<exception type + the failing line, as `path/to/File.kt:42`>

## Why
<root cause in 2–4 sentences: the bad state, where it came from, why it reached this line>

## Evidence
<the specific frames / code / history that support this, with file:line references>

## Fix
<the concrete change; a code sketch only when prose is not enough>

## Verify
<the command, test, or reproduction step that proves it — e.g. `./gradlew :app:testDebugUnitTest --tests '*FooTest*'`>

## Also worth checking
<other call sites with the same flaw, or the guard that would have caught this earlier — omit if none>

用户要求修复时再应用修复。如果用户只问错误是什么意思,则在分析后停止——不要开始编辑代码。

第 7 步:验证修复结果

应用修复后,运行项目自己的验证流程(测试、构建、分析器),并报告实际结果——包括验证仍然失败的情况。未经运行验证的修复只是提议,不算修复。

如果同类错误可能也出现在其他地方,请用一行提及。不要扩展为对周边模块的重构。

操作模式

此技能支持三种模式;根据用户的请求选择:

操作用户意图输出
explain-error“这是什么意思?”步骤 1–4,用通俗语言解释,不修改代码
analyze(默认)“为什么会崩溃”,或只粘贴跟踪信息步骤 1–6,提供完整报告和建议的修复方案
fix“修复这个”“javítsd”步骤 1–7,应用更改并验证

关键约束

  • 绝不编造帧、行号或文件路径。 如果跟踪被截断或混淆,请说明缺少什么,不要自行补全。
  • 分析任何发布版或混淆后的跟踪前,先进行符号化。 未符号化的诊断只是猜测。
  • 代码可用时,务必阅读失败行上的实际源码。 仅在无法获取代码时,才根据跟踪本身进行分析。
  • 区分确定程度。 将每条结论标记为已确认(可指出对应代码行)、较可能(符合证据,但未经验证)或推测(需要更多数据)。不要把第三种说成第一种。
  • 每份报告只分析一个根因。 如果跟踪显示多个相互独立的故障,应分别分析,不要混在一起。
  • 不要把原始日志贴回给用户。 只引用能够说明诊断依据的少数几行。
  • 不要擅自扩大范围。 只修复用户询问的崩溃;列出相关问题,但不要重构。
  • 绝不要将崩溃日志、.ips 文件或映射文件发送到外部服务。 这些文件通常包含设备标识符、用户路径和内部符号名称。

参考资料

  • symbolication.md — 各平台的反混淆和符号化;分析发布版前先完成此步骤
  • kotlin-android-kmp.md — Kotlin/JVM、Android、协程、ANR、Kotlin/Native、Compose 和 CMP
  • flutter-dart.md — FlutterError、渲染/布局错误、异步间隙、平台通道
  • swift-apple.md — .ips 崩溃报告、异常类型、Swift Concurrency、Objective-C 异常
  • rust-cpp.md — Rust panic 和错误链;C++ 段错误、核心转储、消毒器、NDK
  • other-languages.md — Python、JavaScript/TypeScript、Go、仅包含 Java 的跟踪
  • worked-examples.md — 各平台的跟踪示例及完整分析

评论

支持 Markdown