codeprobe-error-handling について
ソフトウェアのエラー処理と耐障害性を調べる codeprobe スキルです。例外処理、入力検証、外部呼び出し、トランザクション、エラーレスポンス、ログを確認します。
主な機能
- 01握りつぶされた例外や広すぎる捕捉の検出
- 02外部呼び出しのエラー処理の確認
- 03検証処理と null 前提の確認
- 04リトライ、タイムアウト、トランザクション安全性の確認
- 05エラーレスポンスと障害ログの確認
活用シーン
- 01コードベースの例外処理の監査
- 02外部呼び出しのタイムアウトとリトライの確認
- 03検証処理とデータベーストランザクションのレビュー
- 04障害ログやエラーレスポンスの不足箇所の特定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ machineroom-dev/ codeprobe --skill codeprobe-error-handlingインストール後、Claude Code で/codeprobe-error-handlingを入力して読み込まれたか確認します。
詳細
スタンドアロンモード
オーケストレーター経由ではなく直接呼び出された場合は、まず次の手順を実行する必要があります。
- 出力契約、実行モード、制約を確認するため、
../codeprobe/shared-preamble.md(ユーザーのプロジェクトではなく、この SKILL.md の場所を基準に、隣接するcodeprobeスキルディレクトリから解決)を読みます。 - プロジェクトの技術スタックに応じて、
../codeprobe/references/(同じ方法で解決)から該当するリファレンスファイルを読み込みます。 - ユーザーが別の指定をしない限り、
fullモードをデフォルトにします。
エラーハンドリングとレジリエンスのチェッカー
対象範囲
このサブスキルでは、次のカテゴリにおけるエラーハンドリングとレジリエンスの問題を検出します。
- 握りつぶされた例外 — 空の catch ブロック、再スローや処理を行わず、catch してログに記録するだけの処理
- エラーハンドリングの欠如 — try/catch を使用しない外部 API 呼び出し、未処理の Promise 拒否
- エラー情報 — 汎用的なエラーメッセージ、内部情報の漏えい、構造化レスポンスの欠如
- 再試行とサーキットブレーカー — 外部呼び出しのタイムアウトなし、一時的な障害に対する再試行なし
- 検証 — 入力検証の欠如、暗黙的な null の想定、型変換のバグ
- トランザクションの安全性 — トランザクションを使わない複数ステップの DB 操作、ロールバックの欠如
- ロギング — 重要な処理経路でのログ記録なし、相関 ID の欠如
検出対象外
- ログ内の機密データ —
codeprobe-security(SECプレフィックス)の対象です。このサブスキルでは、データ漏えいではなく、ログ記録の欠如や相関 ID がないといった構造上の問題を検出します。 - テストファイル — テストでの例外処理には異なるパターンがあり、より単純であることが想定されます。
- フレームワークが生成する例外ハンドラー(例:Laravel の
Handler.php、意図的に最小限に抑えられた Next.js のエラーバウンダリー)— これらはスキャフォールドのデフォルトであり、開発者の見落としではありません。 - 意図的に簡素なエラーハンドリングを行う CLI スクリプト(出力して終了)— コマンドラインツールでは、エラーを出力してゼロ以外のコードで終了するパターンが有効なことがよくあります。
- 既知で無害な特定の例外を意図的に握りつぶす catch ブロック(その理由を説明するコメントがある場合)— 開発者が根拠を記録している場合は、その判断を尊重してください。
- 主にセキュリティ脆弱性に該当する問題(例:認証の回避、インジェクション、データ漏えい)。エラーハンドリングにも影響する場合であっても、これらは
codeprobe-securityの対象です。両方のサブスキルが同じ箇所を検出した場合、オーケストレーターが重複を排除し、セキュリティの検出結果を優先します。
検出手順
握りつぶされた例外
| ID プレフィックス | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | 空の catch ブロック | 本文が空、pass のみ、// ignored のみ、またはコメントのみの catch ブロックを検索します。JS/TS では catch (e) {}、PHP では catch (\Exception $e) {}、Python では except: pass または except Exception: pass が該当します。 | Major |
ERR | catch してログに記録するだけで、対処しない処理 | ログまたは print 文だけを含み、再スロー、エラーの返却、復旧処理のいずれも行わない catch ブロックを探します。ログ記録後、例外が握りつぶされています。 | Minor |
ERR | 範囲が広すぎる例外の捕捉 | catch (\Exception $e)、catch (Exception e)、Python の裸の except:、すべてのエラーを捕捉する catch (e) が該当します。より具体的な例外型を捕捉すべき場合に検出します。 | Major |
エラー処理の不足
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | try/catch のない外部 API 呼び出し | HTTP クライアント呼び出し(Guzzle、axios、fetch、requests、HttpClient)、決済 SDK 呼び出し(Stripe、PayPal)、AWS SDK 呼び出し、その他の外部サービス連携を検索します。これらの呼び出しが try/catch または .catch() で囲まれていない場合にフラグを付けます。 | Major |
ERR | 処理されない Promise の拒否 | .catch() または周囲の try/catch がない非同期関数や Promise チェーンを検索します。浮遊 Promise(await せずに呼び出される非同期呼び出し)を探します。Node.js では、unhandledRejection ハンドラーがないか確認します。 | Major |
ERR | エラー処理のないファイル I/O | IOError/FileNotFoundError に対する try/catch がない file_get_contents、fopen、fs.readFile、open()(Python)。 | Minor |
エラー情報
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | 汎用的なエラーメッセージ | エラーコードやクライアントが対応するための詳細情報がなく、「問題が発生しました」「内部サーバーエラー」などのメッセージのみを返す API レスポンス。 | Minor |
ERR | API 利用者への内部エラー情報の漏えい | API の JSON/HTML レスポンスに公開されている例外メッセージ、スタックトレース、SQL エラー、ファイルパス。エラー処理ミドルウェアの設定を確認します。 | Major |
ERR | 構造化されたエラーレスポンスの不足 | 一貫した構造(エラーコードフィールドやメッセージフィールドがない、エンドポイント間で形式に一貫性がない)を持たずにエラーを返す API エンドポイント。 | Minor |
リトライとサーキットブレーカー
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | タイムアウトのない外部サービス呼び出し | タイムアウト設定のない HTTP クライアント呼び出し。timeout オプションのない Guzzle、timeout のない axios、timeout パラメーターのない requests、AbortController のない fetch。 | Major |
ERR | 一時的な障害に対するリトライがない | 一時的に失敗する可能性(HTTP 429、503、ネットワークエラー)のある外部 API 呼び出しに、リトライの仕組みがない。 | Minor |
ERR | 連鎖的な障害に対するサーキットブレーカーがない | マイクロサービスアーキテクチャにおけるサービス間呼び出しに、サーキットブレーカーまたはフォールバックパターンがない。 | Suggestion |
バリデーション
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | 処理前の入力バリデーション不足 | 外部入力(リクエストパラメーター、ファイル内容、API ペイロード)を受け取り、検証せずにそのまま使用する関数。 | Major |
ERR | null を暗黙に前提とする処理 | null チェックをせずに、null/undefined の可能性がある値のプロパティにアクセスしたり、メソッドを呼び出したりすること。null の可能性がある戻り値に対して . でアクセスを連鎖させること。 | Minor |
ERR | 型変換のバグ | セキュリティ上重要な比較で、PHP の === ではなく == を使用すること。JS の === ではなく == を使用すること。予期しない結果を招く可能性のある暗黙の型変換。 | Minor |
トランザクションの安全性
| ID Prefix | 検出対象 | 検出方法 | 重大度 |
|---|---|---|---|
ERR | トランザクションを使わない複数ステップの DB 操作 | 同じメソッド内で複数の INSERT/UPDATE/DELETE クエリを連続して実行し、DB::transaction()、atomic()、BEGIN/COMMIT、または同等の仕組みを使っていないこと。いずれかのステップが失敗すると、データが不整合な状態になります。 | Critical |
ERR | 適切なロールバックのないトランザクション | 例外を捕捉してもロールバックしないトランザクションブロック、または成功を確認せずにトランザクション後のコードが成功を前提とすること。 | Major |
ロギング
| ID プレフィックス | 検出対象 | 検出方法 | 重要度 |
|---|---|---|---|
ERR | 重大な失敗経路でロギングが行われていない | 重要なビジネスロジック(決済、認証、注文処理)の catch ブロックにロギングが含まれていないか確認します。失敗が記録されないまま発生します。 | Major |
ERR | 相関 ID/リクエスト ID が不足している | リクエスト処理コード内のログ出力に、相関 ID、リクエスト ID、トレース ID が含まれていないか確認します。分散システムの問題をデバッグできなくなります。 | Minor |
ID プレフィックスと修正プロンプトの例
すべての指摘には ERR- プレフィックスを付け、ERR-001、ERR-002 のように連番を振ります。
修正プロンプトの例
- "
PaymentService@charge(55 行目)の Stripe API 呼び出しを、\Stripe\Exception\ApiErrorExceptionを対象とする try/catch で囲んでください。$orderIdと$amountを含むコンテキストとともにエラーをログに記録し、ユーザーにわかりやすいメッセージを含むドメイン固有のPaymentFailedExceptionをスローしてください。" - "現在、Order、OrderItems、Payment レコードを 3 つの別々のクエリで作成している
OrderService@create(40~65 行目)の注文作成フローを、DB::transaction()で囲んでください。いずれかの処理が失敗した場合は、すべてロールバックする必要があります。" - "
app/Services/NotificationService.php:88の空の catch ブロックを、適切なエラー処理に置き換えてください。通知のコンテキストとともに例外をログに記録したうえで、再スローするか(重要な通知の場合)、メトリクスを記録して握りつぶすか(重要でない場合)を判断してください。" - "
ExternalApiClient.php:30の HTTP クライアント呼び出しに、タイムアウトとリトライの設定を追加してください。一時的なネットワーク障害に対応するため、Guzzle リクエストに->timeout(10)->retry(3, 100)を使用してください。"
コメント
Markdown 対応