mcpField
E
error-handling-standardizer

error-handling-standardizer

github.com/patricio0312rev開発63257 回インストール41 週間前に更新
リポジトリ

error-handling-standardizer について

アプリケーション全体で一貫性があり、デバッグしやすいエラー処理を構築する開発スキルです。エラー分類、ハンドラーミドルウェア、構造化ログ、安全なクライアント向けメッセージ、非同期エラー処理を扱います。

主な機能

  1. 01カスタムエラークラスと分類の定義
  2. 02エラーミドルウェアとステータス対応の設定
  3. 03コンテキスト付き構造化ログの記録
  4. 04クライアント向け安全なエラーメッセージ
  5. 05非同期ルートのエラーラップ

活用シーン

  1. 01アプリケーション各モジュールのエラー応答統一
  2. 02内部エラーのクライアントへの漏えい防止
  3. 03リクエストエラーへのログコンテキスト追加
  4. 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 ステータスコードのマッピング
  • 構造化ログの設定
  • 安全なクライアント向けエラーメッセージ
  • 非同期エラーラッパー
  • エラーの監視/アラート
  • エラーコードのドキュメント

コメント