debugging-methodology について
debugging-methodologyは、実行時エラー、リソース枯渇、性能低下などの不具合を体系的に調査・修正するスキルです。再現と失敗地点での証拠確認を重視し、既存の見立てではなく測定に基づいて原因を特定します。
主な機能
- 01手順に沿った再現・特定・検証
- 02仮説の記録と調査範囲の絞り込み
- 03失敗地点での実リソース測定
- 04センチネル値や既定識別子の認識
- 05システムレベル調査ツールの参照
活用シーン
- 01メモリリークや競合状態の調査
- 02枯渇・断片化・アロケーター問題の切り分け
- 03エラーに示された対象が実在するか確認
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ laurigates/ claude-plugins --skill debugging-methodologyインストール後、Claude Code で/debugging-methodologyを入力して読み込まれたか確認します。
同梱ファイルREFERENCE.md
詳細
デバッグの方法論
バグを見つけて修正するための体系的なアプローチです。
このスキルを使う場面
| 次のような場合はこのスキルを使います... | 次のような場合は代わりに別の方法を使います... |
|---|---|
| 発生中のバグ、メモリリーク、競合状態、パフォーマンスの低下を診断する | エラーが握りつぶされてバグが隠れている → code-hidden-failures --track errors |
| 再現、切り分け、根本原因について検討する | 空の結果でもエラーにならずバグが隠れている → code-hidden-failures --track degradation |
| システムレベルの調査に strace/eBPF/perf のどれを使うか選ぶ | 根本原因が判明した後、周辺コードの品質を確認する → code-review |
| 仮説を記録し、二分探索で障害箇所を絞り込む | 修正後に問題のあるモジュールをリファクタリングする → code-refactor |
基本原則
- オッカムの剃刀 - まず最も単純な説明から始めます
- 二分探索 - 問題の範囲を体系的に絞り込みます
- 証拠を保全する - 変更を加える前に状態を把握します
- 仮説を記録する - 試したことと、うまくいかなかったことを追跡します
デバッグのワークフロー
1. Understand → What is expected vs actual behavior?
2. Reproduce → Can you trigger the bug reliably?
3. Locate → Where in the code does it happen?
4. Diagnose → Why does it happen? (root cause)
5. Fix → Minimal change to resolve
6. Verify → Confirm fix works, no regressions
よくあるバグのパターン
| 症状 | 考えられる原因 | 最初に確認すること |
|---|---|---|
| TypeError/null | null チェックの不足 | 入力検証 |
| 1つずれる | ループ境界、配列インデックス | 境界条件 |
| 競合状態 | 非同期処理のタイミング | await/promise の処理 |
| インポートエラー | パス/モジュールの解決 | ファイルパス、エクスポート |
| 型の不一致 | 誤った型の受け渡し | 関数シグネチャ |
| 不安定なテスト | タイミング、共有状態 | テストの分離 |
障害発生地点で診断する — センチネル値とリソースの読み取り
~/.claude/rules/diagnose-at-the-failure-point.md から昇格されたもので、スタブには2つのゲート行が残されています。ツールやライブラリが障害を報告するとき、診断を誤らせることの多い表面的な特徴が2つあります。それは、エラー内で名前が示されている対象と、調査を始める前から引き継いでいる問題の捉え方です。どちらも、障害が起きたまさにその地点で実態と照合すれば、簡単に確認できます。
1. エラー内で名前が示されている対象は、実在するオブジェクトではなくセンチネル値/デフォルト値かもしれません
小さい値/ゼロ値/デフォルト値の識別子で対象を示すエラー(Memory page 0 doesn't exist、id 0、空文字列の名前、index -1、0.0.0.0、null UUID)は、問題を起こした実在の対象ではなく、未初期化またはセンチネルのデフォルト値を報告していることがよくあります。対象について仮説を立てる前に、その識別子がフォールバック経路ではなく、実際に成功した処理(割り当て/検索/登録の完了)に由来することを確認してください。
典型的な障害事例(2026-07、cubecl CUDA):
couldn't find resource for that handle: Memory page 0 doesn't existは、引き継ぎ時の問題、上流のトラッカー、そして私自身によって、何度も「ページ0」を破損させるメモリプールの再利用競合だと解釈されていました。実際にはMemoryLocation::uninit() = {pool:0,page:0}でした。割り当ての失敗によってハンドルがバインドされないままゼロのデフォルト値になり、バインドされていないハンドルを下流で検索するたびに「ページ0」と報告されていたのです。プールの再利用は一度も発生していませんでした。決め手となったのは機械的な対応関係です。「見つからない」ハンドルの種類数が、割り当て失敗数とぴったり一致していました。
決め手となるのは、多くの場合、上流の何かと一致する件数または比率(見つからない対象の件数 == 失敗数)です。対象が実在すると決めつける前に、この点を確認してください。
2. 枯渇の症状が出たら、障害発生時点で実際のリソースを確認する
OOM/out of memory/can't allocate/ENOSPC/too many open files/
pool exhausted は、実際の枯渇、断片化、マネージャー/アロケーターのバグという、3 種類の原因に対する症状です。障害発生時点で測定すれば、どれに該当するかを判別できます。
| 症状 | 障害発生時点で確認するもの | 実際に枯渇している条件 |
|---|---|---|
| CUDA/GPU の OOM | cuMemGetInfo(空き、合計) | 空き ≪ 要求量 |
ENOSPC | 対象のファイルシステムに対する df | 空き ≈ 0 |
EMFILE/ファイル数超過 | fd 数と ulimit -n の比較 | 数 ≈ 上限 |
| アロケーター/プールの「満杯」 | プールの in_use と reserved とデバイスの合計 | in_use ≈ デバイスの合計 |
失敗した呼び出し箇所に計測処理を入れて、この値を出力してください。数秒前に採取したサンプラーの結果から推測してはいけません(サンプル間にピークが発生している可能性があります)。同じケースで、失敗した malloc の時点で cuMemGetInfo を実行したところ、25.2 GB 中 0.58 GB が空きでした。断片化でもプールのバグでもなく、実際に満杯だったのです。この測定結果によってアロケーターの原因探しは終わりました。ワーキングセットが単純に GPU の容量を超えていたのです。競合していたすべての仮説(回収競合、カーソルガード、回収前の同期、解像度という「調整手段」)は、議論ではなく測定によってすでに否定されていました。
障害発生時点の証拠 > 与えられた見立て > もっともらしい仕組み。 自信たっぷりに書かれた issue、メンテナーが示した根本原因、エラーメッセージ自体の文言は、いずれも結論ではなく、検証すべき入力情報です。仮説と測定結果が食い違ったら、優先すべきなのは測定結果です。仮説に合わせてパッチを当てるのではなく、原因を再診断してください。エラーが不審な丸め値/ゼロ/デフォルト値で対象を示している場合、「リソース枯渇」エラーの修正方法がその原因に左右される場合、または引き継いだ情報や上流のトラッカーですでに根本原因が断定されている場合に、この問題は起こります。たった一度の手軽な確認を省くと、5 秒で済む cuMemGetInfo/df/件数の確認を、実際には起きていない仕組みを何度も調べる作業と引き換えにすることになります。関連項目:agent-patterns-plugin:probe-input-integrity(自分で考えた id)、git-plugin:git-issue-scoping と git-plugin:git-upstream-fix-check(引き継いだ見立てを鵜呑みにしない)、agent-patterns-plugin:tool-result-traps(形式は正しくても、実態とひそかに食い違っている出力)。
デバッグ時の質問
行き詰まったら、次の点を確認してください。
- 最近、原因になりそうな変更がありましたか?
- すべての環境で発生しますか、それとも特定の環境だけですか?
- バグは自分のコードにありますか、それとも依存関係にありますか?
- 間違っている可能性のある前提はありませんか?
- 最小限の再現コードを書けますか?
効果的なデバッグの実践方法
- 変更対象を絞る:仮説を立て、一度に一つだけ変更します
- 適切なデバッガーを使う:可能であれば、ブレークポイントを使ってコードをステップ実行します
- 根本原因を見つける:問題の発生源までたどり、原因そのものを修正します
- まず再現する:修正を試みる前に、最小限の再現コードを作成します
- 修正を検証する:問題が解決し、テストに合格することを確認します
システムレベルのツール(メモリ解析、プロファイリング、strace/eBPF トレーシング、ネットワークデバッグ)および言語固有のデバッガーコマンドについては、REFERENCE.md を参照してください。