error-handling-patterns について
アプリケーション、API、分散システムのエラー処理を支援するスキルです。エラー方式の選択、復旧、診断、代表的な対処パターンを扱います。
主な機能
- 01例外と Result 型の比較
- 02復旧可能・致命的エラーの分類
- 03リトライとサーキットブレーカーの適用
- 04コンテキストの保持とリソース解放
活用シーン
- 01障害に強い API の設計
- 02本番環境の障害調査
- 03非同期エラーの処理
- 04ユーザー向けエラーメッセージの改善
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ wshobson/ agents --skill error-handling-patternsインストール後、Claude Code で/error-handling-patternsを入力して読み込まれたか確認します。
同梱ファイルreferences/details.md
詳細
エラーハンドリングのパターン
堅牢なエラーハンドリング戦略で、障害を適切に処理し、優れたデバッグ体験を提供する復元力のあるアプリケーションを構築します。
このスキルを使う場面
- 新機能にエラーハンドリングを実装するとき
- エラーに強い API を設計するとき
- 本番環境の問題をデバッグするとき
- アプリケーションの信頼性を向上させるとき
- ユーザーと開発者にとってより良いエラーメッセージを作成するとき
- リトライとサーキットブレーカーのパターンを実装するとき
- 非同期・並行処理のエラーを処理するとき
- フォールトトレラントな分散システムを構築するとき
中核となる概念
1. エラーハンドリングの思想
例外 vs Result 型:
- 例外: 従来の try-catch、制御フローを乱す
- Result 型: 成功・失敗を明示、関数型のアプローチ
- エラーコード: C 言語スタイル、規律が必要
- Option/Maybe 型: null 許容値向け
それぞれを使う場面:
- 例外: 予期しないエラー、例外的な状況
- Result 型: 想定内のエラー、バリデーションの失敗
- パニック・クラッシュ: 回復不能なエラー、プログラミングのバグ
2. エラーの分類
回復可能なエラー:
- ネットワークタイムアウト
- ファイルの欠落
- 不正なユーザー入力
- API のレート制限
回復不能なエラー:
- メモリ不足
- スタックオーバーフロー
- プログラミングのバグ(null ポインタなど)
詳細なパターンと実例
詳細なパターンのドキュメントは references/details.md にあります。上記のナビゲーション階層では不十分な場合は、そのファイルを読んでください。
ベストプラクティス
- 早期に失敗する: 入力を早く検証し、素早く失敗する
- コンテキストを保持する: スタックトレース、メタデータ、タイムスタンプを含める
- 意味のあるメッセージ: 何が起きたか、どう修正するかを説明する
- 適切にログを取る: エラー = ログに記録、想定内の失敗 = ログを溢れさせない
- 適切なレベルで処理する: 意味のある処理ができる場所でキャッチする
- リソースをクリーンアップする: try-finally、コンテキストマネージャー、defer を使う
- エラーを握りつぶさない: ログに記録するか再スローする、黙って無視しない
- 型安全なエラー: 可能な場合は型付きエラーを使う
# Good error handling example
def process_order(order_id: str) -> Order:
"""Process order with comprehensive error handling."""
try:
# Validate input
if not order_id:
raise ValidationError("Order ID is required")
# Fetch order
order = db.get_order(order_id)
if not order:
raise NotFoundError("Order", order_id)
# Process payment
try:
payment_result = payment_service.charge(order.total)
except PaymentServiceError as e:
# Log and wrap external service error
logger.error(f"Payment failed for order {order_id}: {e}")
raise ExternalServiceError(
f"Payment processing failed",
service="payment_service",
details={"order_id": order_id, "amount": order.total}
) from e
# Update order
order.status = "completed"
order.payment_id = payment_result.id
db.save(order)
return order
except ApplicationError:
# Re-raise known application errors
raise
except Exception as e:
# Log unexpected errors
logger.exception(f"Unexpected error processing order {order_id}")
raise ApplicationError(
"Order processing failed",
code="INTERNAL_ERROR"
) from e
よくある落とし穴
- 範囲が広すぎるキャッチ:
except Exceptionはバグを隠す - 空の catch ブロック: エラーを黙って握りつぶす
- ログを取って再スロー: ログエントリが重複する
- クリーンアップしない: ファイルや接続を閉じ忘れる
- 不十分なエラーメッセージ: 「エラーが発生しました」は役に立たない
- エラーコードを返す: 例外か Result 型を使う
- 非同期エラーの無視: 未処理の Promise の reject
コメント
Markdown 対応