45395 - シコウサクゴ -

/sc:troubleshootでデバッグを構造化する:Claude Codeの分析コマンド活用術

2026-04-03
AI駆動開発
AI駆動開発
Claude Code
デバッグ
トラブルシューティング
sc:troubleshoot
Last updated:2026-04-05
10 Minutes
1944 Words

Claude Codeでデバッグするとき、「エラーが出ました、直してください」と丸投げすると、場当たり的な修正が返ってくることがあります。根本原因を特定せずに表面的な修正をすると、別の場所で同じ問題が再発します。

本記事では、/sc:troubleshoot(構造化トラブルシューティング)と/sc:analyze(コード分析)を使ったデバッグの手法と、実際のインシデント対応での活用例を記録します。


「直してください」の問題

よくある失敗パターン

1
人間: 「このエラーを直してください」
2
TypeError: unsupported operand type(s) for +: 'NoneType' and 'float'
3
4
AI: 「None チェックを追加しました」
5
if value is not None:
6
result = value + offset
7
8
人間: 「テストは通ったけど、なぜ value が None になるのか未解決」

Noneチェックの追加はエラーを消しますが、「なぜvalueNoneなのか」という根本原因は解決していません。上流のデータパイプラインに問題があるかもしれません。


/sc:troubleshoot の構造

/sc:troubleshootは、以下の構造化されたプロセスでデバッグを進めます。

Step 1: 症状の記録

1
[症状]
2
- エラーメッセージ: TypeError: unsupported operand type(s) for +
3
- 発生場所: unified_analyzer.py:245
4
- 発生条件: source_alphaの分析時のみ
5
- 頻度: 毎回
6
- 環境: 本番(launchd経由)

Step 2: 仮説の列挙

AIが複数の仮説を挙げます。

1
[仮説]
2
H1: 外部APIのレスポンスにNullフィールドが含まれている
3
H2: 中間データのParquetファイルにNaN値がある
4
H3: 前段の計算で例外がキャッチされ、Noneが返されている
5
H4: 環境変数の不足で設定ファイルが読めていない

Step 3: 仮説の検証(証拠収集)

各仮説を検証するためのコマンドを実行します。

1
# H1の検証: APIレスポンスの確認
2
response = api_client.get_records("source_alpha", count=10)
3
print(response) # → Nullフィールドなし → H1棄却
4
5
# H2の検証: Parquetの中身を確認
6
df = pd.read_parquet("pipeline_source_alpha_*.parquet")
7
print(df.isnull().sum()) # → moving_avg_14列に3個のNaN → H2有力
8
9
# H3の検証: 前段の処理のログ確認
10
# → NaN発生は createIntermediateData.py の出力段階から存在 → H2確定

Step 4: 根本原因の特定

1
[根本原因]
2
createIntermediateData.py がAPIから取得したデータの先頭3行では
3
移動平均(Moving Average)の計算に必要な過去14件のデータポイントが
4
不足しているため、moving_avg_14がNaNとなる。
5
6
下流の unified_analyzer.py ではNaN値を想定した処理がないため、
7
NoneType + float のTypeErrorが発生する。

Step 5: 修正と再発防止

1
# 根本原因の修正: データ生成時にNaN行を除去
2
df = df.dropna(subset=["moving_avg_14"])
3
4
# 防御的チェックの追加(上流が修正されても安全)
5
if pd.isna(avg_value):
6
logger.warning(f"moving_avg_14 is NaN for {source}, skipping")
7
continue

/sc:analyze の活用

/sc:analyzeは、コード変更の品質・セキュリティ・パフォーマンスを多角的に分析します。

変更前の影響範囲分析

1
プロンプト:
2
/sc:analyze unified_analyzer.py の _analyze_source メソッドに
3
moving_avg_14 の NaN チェックを追加する変更の影響範囲を分析してください。
1
分析結果:
2
[品質]
3
- 変更箇所の循環的複雑度: +1(許容範囲)
4
- テストカバレッジへの影響: NaN入力のテストケース追加が必要
5
6
[セキュリティ]
7
- 問題なし
8
9
[パフォーマンス]
10
- dropna()は全行スキャンのため、大量データでは影響あり
11
- 推奨: 計算の先頭ウォームアップ期間を除外するアプローチ
12
13
[影響範囲]
14
- unified_analyzer.py: 直接変更
15
- outputFileGenerator.py: moving_avg_14を参照(動作変更なし)
1 collapsed line
16
- batch_engine.py: 中間データにmoving_avg_14が含まれる前提(変更不要)

施策間の競合検出

1
プロンプト:
2
/sc:analyze 施策B3(バッチ分割処理)と施策B4(Z-score閾値判定)の
3
コードを分析し、リソース操作の競合がないか確認してください。
1
分析結果:
2
⚠️ 潜在的リスク検出:
3
4
B3の _allocate_grid_resource() と B4の _check_zscore_threshold() が
5
同一データソースのリソースを操作する可能性があります。
6
7
B3: リソースを確保 → resource_id を取得
8
B4: 全リソースをスキャン → Z-score 閾値超えで解放
9
10
B4は「自分が確保したリソース」と「B3が確保したリソース」を
11
区別できない設計になっています。
12
13
推奨: リソースにタグ(施策ID)を付与し、
14
自施策のリソースのみを操作する設計に変更。

実際のインシデント対応事例

事例: 7日間の出力ファイル生成停止

症状: 日次の出力ファイル(分析結果を記録したJSONファイル)が7日間生成されていなかった。エラーログなし。

通常のデバッグ: 「ログにエラーがないからわからない」で止まる。

/sc:troubleshootでの対応:

1
Step 1 [症状]:
2
- output_*.json が7日間生成されていない
3
- launchdジョブは正常実行(launchctl listに表示)
4
- stderrログにエラーなし
5
- 最終正常動作: 03-01
6
7
Step 2 [仮説]:
8
H1: daily_preparation.py が異常終了しているが、exitコード0で終了
9
H2: データ読み込み対象ファイルが空で、処理がスキップされている
10
H3: インポートエラーが発生しているが、except句で握りつぶされている
11
H4: 別施策のデプロイでモジュール名が変更された
12
13
Step 3 [検証]:
14
# H4の検証: git log で 03-01 前後のコミットを確認
15
git log --oneline --since="2026-02-28" --until="2026-03-08"
17 collapsed lines
16
# → 03-01に施策B4のデプロイあり。core/ 配下のファイル名変更を含む
17
18
# 当該ファイルのインポートを確認
19
python -c "from core.shared.tier_classifier import TierClassifier"
20
# → ModuleNotFoundError! (ただしlaunchd環境ではexceptで握りつぶし)
21
22
Step 4 [根本原因]:
23
施策B4のデプロイで _dataProcessingEngineA/core/shared/ 内のモジュール名が
24
変更されたが、daily_preparation.py では旧名でインポートしていた。
25
launchd環境では PYTHONPATH の設定により、相対インポート
26
`from core.shared.X import Y` が解決できず ModuleNotFoundError が発生。
27
しかし外側の try-except で握りつぶされ、エラーログなしで終了していた。
28
29
Step 5 [修正]:
30
1. 絶対インポートに変更: from _dataProcessingEngineA.core.shared.X import Y
31
2. CI/CD に絶対インポート強制チェックを追加
32
3. CLAUDE.md にインポートルールを追記

この事例が、CLAUDE.mdの「絶対インポートパターン(CI/CD自動検証・BLOCKING)」ルール追加のきっかけとなりました。


/sc:troubleshoot を効果的に使うコツ

1. 症状を正確に記述する

1
❌ 「動きません」
2
✅ 「source_alphaの分析時のみ、unified_analyzer.py:245でTypeError。
3
source_betaでは正常。launchd経由の本番環境で発生。」

2. ログは省略せずに貼る

1
❌ 「エラーが出ました」
2
✅ 「以下のstderrログを確認してください:
3
[2026-03-24 09:05:12] ERROR - TypeError: unsupported operand type(s)
4
for +: 'NoneType' and 'float'
5
File "/Users/htada/projects/_dataProcessingEngineA/unified_analyzer.py",
6
line 245, in _analyze_source」

3. 「何を試したか」を伝える

1
✅ 「H1(APIレスポンスの問題)は検証済みで棄却。
2
H2(Parquetデータの問題)を検証中です。」

4. 再発防止策まで求める

1
✅ 「修正だけでなく、同じ種類のバグを今後防ぐための
2
CLAUDE.mdルールまたはテストを提案してください。」

学んだこと

1. 構造化されたデバッグはAIの精度を上げる

仮説→検証→根本原因の流れを明示すると、AIが場当たり的な修正をしなくなります。

2. /sc:analyze は「変更前」に使う

変更後に分析しても手遅れのことがあります。変更前に影響範囲を分析し、問題を予防します。

3. インシデントの教訓をCLAUDE.mdに残す

/sc:troubleshootで特定した根本原因は、CLAUDE.mdのルールとして永続化します。次のセッションでAIが同じ間違いを繰り返しません。


まとめ

構造化デバッグで重要なのは以下の3点です。

  1. /sc:troubleshoot: 症状→仮説→検証→根本原因→再発防止の5ステップで、場当たり的な修正を防止
  2. /sc:analyze: 変更前に影響範囲・品質・セキュリティ・パフォーマンスを多角分析
  3. 教訓の永続化: デバッグで得た知見をCLAUDE.mdのルールに反映し、再発を防止

「エラーを消す」のではなく「エラーの原因を理解し、再発を防ぐ」——構造化されたデバッグがその差を生みます。

Article title:/sc:troubleshootでデバッグを構造化する:Claude Codeの分析コマンド活用術
Article author:45395
Release time:2026-04-03

記事へのご質問・ご感想をお聞かせください

フィードバックを送る