error-handling-standardizer について
アプリケーション全体で一貫性があり、デバッグしやすいエラー処理を構築する開発スキルです。エラー分類、ハンドラーミドルウェア、構造化ログ、安全なクライアント向けメッセージ、非同期エラー処理を扱います。
主な機能
- 01カスタムエラークラスと分類の定義
- 02エラーミドルウェアとステータス対応の設定
- 03コンテキスト付き構造化ログの記録
- 04クライアント向け安全なエラーメッセージ
- 05非同期ルートのエラーラップ
活用シーン
- 01アプリケーション各モジュールのエラー応答統一
- 02内部エラーのクライアントへの漏えい防止
- 03リクエストエラーへのログコンテキスト追加
- 04非同期ルート内の例外処理
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ patricio0312rev/ skills --skill error-handling-standardizerインストール後、Claude Code で/error-handling-standardizerを入力して読み込まれたか確認します。
詳細
エラー処理の標準化
アプリケーション全体で、一貫性がありデバッグしやすいエラー処理を構築します。
エラーの分類
export class AppError extends Error {
constructor(
public code: string,
public message: string,
public statusCode: number = 500,
public isOperational: boolean = true,
public details?: any
) {
super(message);
Error.captureStackTrace(this, this.constructor);
}
}
export class ValidationError extends AppError {
constructor(details: Record<string, string[]>) {
super("VALIDATION_ERROR", "Validation failed", 400, true, details);
}
}
export class NotFoundError extends AppError {
constructor(resource: string) {
super("NOT_FOUND", `${resource} not found`, 404);
}
}
export class UnauthorizedError extends AppError {
constructor(message = "Unauthorized") {
super("UNAUTHORIZED", message, 401);
}
}
export class ForbiddenError extends AppError {
constructor(message = "Forbidden") {
super("FORBIDDEN", message, 403);
}
}
エラーハンドラーミドルウェア
export const errorHandler = (
err: Error,
req: Request,
res: Response,
next: NextFunction
) => {
// Log error
logger.error("Request error", {
error: err.message,
stack: err.stack,
path: req.path,
method: req.method,
requestId: req.id,
});
// Operational errors (known)
if (err instanceof AppError && err.isOperational) {
return res.status(err.statusCode).json({
success: false,
error: {
code: err.code,
message: err.message,
details: err.details,
trace_id: req.id,
},
});
}
// Programming errors (unknown)
return res.status(500).json({
success: false,
error: {
code: "INTERNAL_ERROR",
message: "An unexpected error occurred",
trace_id: req.id,
},
});
};
構造化ログ
import winston from "winston";
export const logger = winston.createLogger({
level: "info",
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: "error.log", level: "error" }),
new winston.transports.File({ filename: "combined.log" }),
],
});
// Log with context
logger.error("Payment processing failed", {
userId: user.id,
amount: payment.amount,
error: err.message,
trace_id: req.id,
});
安全なクライアント向けメッセージ
// Never expose internal errors to clients
const getSafeErrorMessage = (err: Error): string => {
if (err instanceof AppError && err.isOperational) {
return err.message; // Safe, user-facing message
}
// Generic message for unexpected errors
return "An unexpected error occurred";
};
非同期エラー処理
// Wrap async routes
export const asyncHandler = (fn: RequestHandler) => {
return (req: Request, res: Response, next: NextFunction) => {
Promise.resolve(fn(req, res, next)).catch(next);
};
};
// Usage
router.get(
"/users",
asyncHandler(async (req, res) => {
const users = await userService.findAll();
res.json(users);
})
);
ベストプラクティス
- カスタムエラークラスを使用します
- 運用上のエラーとプログラミングエラーを区別します
- すべてのエラーをコンテキストとともにログに記録します
- クライアントにスタックトレースを公開しないでください
- デバッグ用にトレース ID を含めます
- エラーの種類ごとに発生率を監視します
- 重大なエラーに対するアラートを設定します
出力チェックリスト
- カスタムエラークラスの定義
- エラーハンドラーミドルウェア
- HTTP ステータスコードのマッピング
- 構造化ログの設定
- 安全なクライアント向けエラーメッセージ
- 非同期エラーラッパー
- エラーの監視/アラート
- エラーコードのドキュメント
コメント
Markdown 対応