| name | problem-solving |
| description | データ不整合・バグ・障害の問題解決ガイドライン。根本原因分析の手順、上流修正優先の原則、ハルシネーション防止チェック、データとコードの整合性検証、多層防御の考え方を扱う。 |
| when_to_use | データ不整合 / バグ / 障害対応時に自動参照。「つじつま合わせ」を避けて上流で直す判断が必要なとき。Triggers: 'バグ修正', 'データ不整合', '障害対応', '根本原因', 'root cause analysis', 'data inconsistency', 'incident', '上流で直す', 'patch vs fix' |
問題解決ガイドライン
データ不整合、バグ、障害対応における問題解決の原則と手順。
1. 根本原因を探る(つじつま合わせをしない)
原則: 上流で直す
問題はデータフローの最も上流で修正する。下流でのパッチ(migrationによるデータ修正、SQL直接更新、出力時の辻褄合わせ)は最終手段。
❌ 悪いパターン
DBに異常データがある → migrationで論理削除 → バッチ再実行
✅ 良いパターン
DBに異常データがある → なぜ入ったか調査 → 取り込みロジックにバリデーション追加
→ 異常データを論理削除 → バッチ再実行
判断フロー
1. 症状を確認(どのデータ・どの機能が、どう間違っているか)
2. データフロー/呼び出しチェーンを遡る(結果 → 計算 → 素材 → 取り込み → 外部ソース)
3. 最初に異常が発生した地点を特定
4. その地点のコードを修正
5. 下流にも防御的チェックを追加(多層防御)
6. 修正後にデータ修復(パイプライン再実行)
典型的な見逃しパターン
| 症状 | 表層の「原因」 | 真の根本原因 |
|---|
| 料金が異常値 | 計算ロジックのバグ | 上流の取り込み時に異常値が混入、バリデーション欠如 |
| レコードの2WD/4WD逆転 | 割当ロジックの不具合 | ORM(Eloquent等)のリレーション型不一致(VARCHAR↔INT)でEager Loadマッチングずれ |
| 一部ユーザーで通知が届かない | 通知送信ロジックの問題 | 論理削除フラグの扱いが delete() と forceDelete() で異なる |
2. ハルシネーション防止チェック
原則: 自分の推論を疑い、必ず裏取りする
コードリーディングだけで判断せず、以下を必ず実行する。
チェックリスト
| チェック項目 | 方法 |
|---|
| カラム/フィールドが存在するか | SHOW COLUMNS / スキーマ定義ファイル確認(コード読みだけで判断しない) |
| データが存在するか | SELECT COUNT(*) FROM table WHERE ... / サンプル取得 |
| 型が一致するか | DB定義(INT/VARCHAR等)とコード側($casts, dataclass 等)の両方を確認 |
| 外部キー/制約が存在するか | マイグレーション履歴を追跡(追加→削除→再追加の変遷を確認) |
| 論理削除ポリシーは何か | SoftDeletes / deleted_at の有無を確認(delete() と forceDelete() の挙動が異なる) |
| 環境差異がないか | dev/staging/prod で同じクエリを実行して比較 |
やってはいけないこと
- コードを読んだだけで「このカラムは存在しない」と断定する
- 1つのテーブル/ファイルだけ見て「データに問題はない」と結論づける
- マイグレーションの最終状態だけ見てFK制約の有無を判断する
- 論理削除の有無を確認せず
delete() を使う
型不一致の検出パターン
ORMリレーションで以下の組み合わせは危険:
| ローカルキー型 | 外部キー型 | リスク |
|---|
| VARCHAR | INT | Eager Load マッチングでずれる可能性 |
| INT | VARCHAR | 同上 |
| string | integer | strict comparison で不一致 |
対策: 型キャストで揃えるか、リレーション定義時に明示的に型変換する。
3. データとコードの整合性検証
原則: 仮説を立てたら、データとコードの両面から検証する
仮説: 「処理Aが項目Xを逆に割り当てている」
→ コード確認: 処理AのJOIN/代入ロジックを読む
→ データ確認: 上流テーブルの値と処理A結果の値を並べて比較
→ 結論: 上流データは正常、処理A結果が逆転 → 処理Aの問題
検証手順テンプレート
SELECT * FROM source_table WHERE conditions ORDER BY updated_at DESC;
SELECT * FROM intermediate_table WHERE conditions;
SELECT * FROM result_table WHERE conditions;
4. 多層防御
1つの修正だけに頼らず、複数レイヤーで防御する
Layer 1: 取り込み時バリデーション(異常値を入れない)
Layer 2: 型整合性(正しくマッチングする)
Layer 3: 処理時の防御条件(異常値があっても除外する)
Layer 4: 出力時検証(結果の妥当性チェック)
単一レイヤーだけだと、将来別の経路で同じ問題が再発する可能性が残る。
5. 修正の進め方
修正順序
- コードの修正を先に行う(根本原因の解消)
- デプロイする
- データの修復は修正済みコードで再実行する(migration や SQL 直接修正ではなく、パイプライン再実行が望ましい)
- 検証で修正を確認する
コミット・PR戦略
- 根本原因の修正とデータ修復は別コミットにする(Revertしやすい)
- 重複コードは発見次第リファクタリングする
- 検証環境向けPRは
cherry-pick-pr 方式で作成し、mainブランチを汚染しない(詳細は branch-fix-strategy スキル参照)
6. 調査レポートの書き方
必須項目
- 症状: 何がどう間違っているか(定量的に)
- 根本原因: コードレベルでどこが問題か(ファイル名:行番号)
- エビデンス: DB クエリ結果 / ログ / コマンド出力で裏付ける
- 修正方針: どのフェーズで何を直すか
- 検証手順: 修正後にどう確認するか
エビデンスの書き方
**エビデンス(staging DB)**:
| key | value | updated_at | 状態 |
|---|---|---|---|
| A100 | 103,081 | 2026-04-01 10:49 | 異常(最新) |
| A100 | 44,390 | 2026-03-11 13:42 | 正常 |
SQLクエリ結果をそのまま貼り、「コードを読んだ推測」と「DBで確認した事実」を明確に区別する。
関連スキル
/ndf:investigation-rules — 調査レポート作成時のエビデンス主義
/ndf:branch-fix-strategy — 複数ブランチへの修正適用戦略
/ndf:logging-guidelines — ログ設計(原因特定を容易にする)