Files
pos-system/docs/vi/skills/error-handling-patterns.md
Ho Ngoc Hai 9b6c585f57 Enhance documentation structure and improve bilingual support across skills
- Updated skill documentation files to include structured metadata for better organization.
- Enhanced bilingual descriptions and guidelines for clarity in both English and Vietnamese.
- Refined sections on usage, best practices, and related skills to ensure consistency across all documentation.
- Improved formatting and removed outdated references to streamline the documentation experience.
- Added best practices checklists to relevant skills for better usability and adherence to standards.
2026-01-01 07:35:44 +07:00

15 KiB

Các Pattern Xử Lý Lỗi

Comprehensive error handling patterns and conventions for GoodGo microservices including error classes, error codes, error middleware, and standardized error responses.

Các patterns và conventions toàn diện về error handling cho GoodGo microservices bao gồm error classes, error codes, error middleware, và standardized error responses.

Tổng Quan

Error handling is a critical aspect of building robust microservices. This guide provides comprehensive patterns and best practices for implementing consistent, maintainable error handling across all services. It covers error types, error code systems, custom error classes, error middleware, and standardized error response formats.

Error handling là khía cạnh quan trọng của việc xây dựng microservices vững chắc. Hướng dẫn này cung cấp các patterns và best practices toàn diện để implement error handling nhất quán và dễ bảo trì trên tất cả các services. Nó bao gồm các loại errors, hệ thống error codes, custom error classes, error middleware, và các định dạng error response đã được chuẩn hóa.

Khi Nào Sử Dụng

Use these error handling patterns when:

  • Implementing error handling in services, controllers, or repositories
  • Creating custom error classes for specific error scenarios
  • Standardizing error responses across APIs
  • Handling exceptions from external services or database operations
  • Implementing error middleware and global error handlers
  • Debugging error scenarios and improving error messages
  • Distinguishing between operational and programming errors

Sử dụng các error handling patterns này khi:

  • Implement error handling trong services, controllers, hoặc repositories
  • Tạo custom error classes cho các error scenarios cụ thể
  • Chuẩn hóa error responses trên các APIs
  • Xử lý exceptions từ external services hoặc database operations
  • Implement error middleware và global error handlers
  • Debug error scenarios và cải thiện error messages
  • Phân biệt giữa operational errors và programming errors

Khái Niệm Chính

Các Loại Lỗi

Lỗi Vận Hành

Expected errors that occur during normal operation. These are errors that the application is designed to handle.

Các lỗi dự kiến xảy ra trong quá trình vận hành bình thường. Đây là các lỗi mà ứng dụng được thiết kế để xử lý.

Characteristics / Đặc Điểm:

  • Examples / Ví dụ: Validation errors, authentication failures, resource not found, rate limiting
  • Handling / Xử Lý: Should be handled gracefully with appropriate HTTP status codes
  • Logging / Ghi Log: Logged as warnings (logger.warn)
  • Exposure / Tiết Lộ: Can expose error details to clients (with caution)
  • Recovery / Phục Hồi: Application can recover and continue operation

Example / Ví dụ: services/iam-service/src/errors/http-error.ts

Lỗi Lập Trình

Unexpected errors due to bugs in code. These indicate problems that need to be fixed.

Các lỗi không mong đợi do bugs trong code. Đây là các vấn đề cần được sửa.

Characteristics / Đặc Điểm:

  • Examples / Ví dụ: Null pointer exceptions, type errors, logic bugs, undefined behavior
  • Handling / Xử Lý: Should be logged with full details for debugging
  • Logging / Ghi Log: Logged as errors (logger.error)
  • Exposure / Tiết Lộ: Should return generic error messages to clients (hide implementation details)
  • Recovery / Phục Hồi: May require application restart or code fixes

Hệ Thống Error Codes

The platform uses a centralized error code system that provides unique identifiers for each error type, enables error tracking and analytics, and supports consistent error handling.

Nền tảng sử dụng hệ thống error codes tập trung cung cấp unique identifiers cho mỗi loại lỗi, cho phép error tracking và analytics, và hỗ trợ error handling nhất quán.

Error Code Format / Định Dạng Error Code: {CATEGORY}_{NUMBER}

  • AUTH_001 - Authentication errors / Lỗi xác thực
  • VALIDATION_001 - Validation errors / Lỗi validation
  • RESOURCE_001 - Resource errors / Lỗi tài nguyên
  • DB_001 - Database errors / Lỗi database
  • SYS_001 - System errors / Lỗi hệ thống

Tham Khảo: services/iam-service/src/errors/error-codes.ts

Patterns

Class Lỗi Cơ Sở

HttpError là base class cho tất cả custom errors:

export class HttpError extends Error {
  public readonly statusCode: number;
  public readonly errorCode: string;
  public readonly isOperational: boolean;
  public readonly details?: any;

  constructor(
    message: string,
    statusCode: number = 500,
    errorCode: string = 'INTERNAL_ERROR',
    isOperational: boolean = true,
    details?: any
  ) {
    super(message);
    this.statusCode = statusCode;
    this.errorCode = errorCode;
    this.isOperational = isOperational;
    this.details = details;
    Error.captureStackTrace(this, this.constructor);
  }

  toApiResponse() {
    return {
      success: false,
      error: {
        code: this.errorCode,
        message: this.message,
        ...(this.details && { details: this.details }),
      },
      timestamp: new Date().toISOString(),
    };
  }
}

Các Class Lỗi Chuẩn

Resource Errors / Lỗi Tài Nguyên:

  • NotFoundError - 404: Resource not found / Tài nguyên không tìm thấy
  • ConflictError - 409: Resource conflict / Xung đột tài nguyên (ví dụ: trùng lặp)
  • BadRequestError - 400: Invalid request / Yêu cầu không hợp lệ

Validation Errors / Lỗi Validation:

  • ValidationError - 422: Input validation failed / Validation đầu vào thất bại

Authentication/Authorization / Xác Thực/Phân Quyền:

  • UnauthorizedError - 401: Authentication required / Yêu cầu xác thực
  • ForbiddenError - 403: Access denied / Truy cập bị từ chối

System Errors / Lỗi Hệ Thống:

  • InternalServerError - 500: Internal server error / Lỗi máy chủ nội bộ (programming error)
  • ServiceUnavailableError - 503: Service temporarily unavailable / Dịch vụ tạm thời không khả dụng
  • DatabaseError - 500: Database operation failed / Thao tác database thất bại
  • ExternalServiceError - 502: External service error / Lỗi dịch vụ bên ngoài

Rate Limiting / Giới Hạn Tốc Độ:

  • RateLimitError - 429: Too many requests / Quá nhiều yêu cầu

Sử Dụng Errors Trong Services

import { NotFoundError, ConflictError } from '../errors/http-error';

export class UserService {
  async getUserById(id: string) {
    const user = await this.repository.findById(id);
    
    if (!user) {
      throw new NotFoundError('User', { id });
    }
    
    return user;
  }
  
  async createUser(data: CreateUserInput) {
    const existing = await this.repository.findByEmail(data.email);
    
    if (existing) {
      throw new ConflictError('User with this email already exists');
    }
    
    return await this.repository.create(data);
  }
}

Tham Khảo: services/iam-service/src/modules/feature/feature.service.ts

Pattern Error Middleware

Global error handler middleware xử lý tất cả errors:

export const errorHandler = (
  err: any,
  req: express.Request,
  res: express.Response,
  _next: express.NextFunction
): void => {
  let statusCode = 500;
  let errorCode = ErrorCode.INTERNAL_ERROR;
  let message = 'Internal server error';
  let isOperational = false;
  
  // Handle HttpError instances
  if (err instanceof HttpError) {
    statusCode = err.statusCode;
    errorCode = err.errorCode as ErrorCode;
    message = err.message;
    isOperational = err.isOperational;
  }
  // Handle Prisma errors
  else if (err.code === 'P2002') {
    statusCode = 409;
    errorCode = ErrorCode.CONSTRAINT_VIOLATION;
    message = 'Resource already exists';
    isOperational = true;
  }
  // Handle Zod validation errors
  else if (err.name === 'ZodError') {
    statusCode = 422;
    errorCode = ErrorCode.VALIDATION_ERROR;
    message = 'Validation failed';
  }
  
  // Log and respond...
};

Tham Khảo: services/iam-service/src/middlewares/error.middleware.ts

Wrapper Lỗi Async

Wrap async route handlers để catch promise rejections:

export const asyncHandler = (fn: Function) => {
  return (req: express.Request, res: express.Response, next: express.NextFunction) => {
    Promise.resolve(fn(req, res, next)).catch(next);
  };
};

// Usage
router.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await userService.getUserById(req.params.id);
  res.json({ success: true, data: user });
}));

Định Dạng Error Response

Định dạng error response đã được chuẩn hóa:

{
  success: false,
  error: {
    code: "RESOURCE_001",
    message: "User not found",
    details?: {
      // Optional additional details (not in production for 5xx errors)
    }
  },
  timestamp: "2024-01-01T00:00:00.000Z"
}

Thực Hành Tốt Nhất

  1. Use Specific Error Classes / Sử Dụng Error Classes Cụ Thể: Sử dụng error class cụ thể nhất cho scenario
  2. Include Context / Bao Gồm Context: Cung cấp error messages hữu ích với context liên quan (resource IDs, field names)
  3. Mark Operational Errors / Đánh Dấu Operational Errors: Set isOperational: true cho các lỗi dự kiến có thể xử lý gracefully
  4. Don't Expose Internal Details / Không Tiết Lộ Chi Tiết Nội Bộ: Ẩn implementation details trong production (stack traces, internal paths)
  5. Log Appropriately / Log Phù Hợp: Sử dụng logger.error() cho programming errors, logger.warn() cho operational errors
  6. Handle Database Errors / Xử Lý Database Errors: Map Prisma errors (P2002, P2025, etc.) sang HTTP errors phù hợp
  7. Use Error Codes / Sử Dụng Error Codes: Luôn sử dụng ErrorCode enum để nhất quán trên các services
  8. Validate Early / Validate Sớm: Validate input sớm trong request pipeline để catch errors trước khi xử lý
  9. Error Middleware Order / Thứ Tự Error Middleware: Đặt error middleware cuối cùng, sau tất cả routes
  10. Async Error Handling / Xử Lý Lỗi Async: Luôn sử dụng asyncHandler cho async route handlers

Lỗi Thường Gặp

  1. Not Using Error Classes / Không Sử Dụng Error Classes: Sử dụng generic Error thay vì specific error classes như NotFoundError
  2. Exposing Stack Traces / Tiết Lộ Stack Traces: Bao gồm stack traces trong production API responses
  3. Ignoring Errors / Bỏ Qua Lỗi: Không xử lý errors trong async operations, để chúng propagate unhandled
  4. Generic Error Messages / Error Messages Chung Chung: Sử dụng error messages mơ hồ không có context (ví dụ: "Error occurred")
  5. Not Logging / Không Log: Quên log errors để debug và monitor
  6. Wrong HTTP Status Codes / HTTP Status Codes Sai: Sử dụng status codes sai cho error types (ví dụ: 500 cho validation errors)
  7. Not Using Error Middleware / Không Sử Dụng Error Middleware: Xử lý errors manually trong mỗi controller thay vì sử dụng middleware
  8. Not Marking Operational Errors / Không Đánh Dấu Operational Errors: Không set isOperational flag, khiến tất cả errors bị coi như programming errors
  9. Inconsistent Error Codes / Error Codes Không Nhất Quán: Không sử dụng centralized ErrorCode enum, dẫn đến error codes không nhất quán
  10. Error Details in Production / Chi Tiết Lỗi Trong Production: Tiết lộ error details (như database queries) trong production responses

Xử Lý Sự Cố

Lỗi Không Được Catch Bởi Middleware

Problem / Vấn Đề: Error không được catch bởi error middleware và gây unhandled promise rejection

Solution / Giải Pháp:

  • Đảm bảo error middleware được thêm cuối cùng trong middleware chain (sau tất cả routes)
  • Sử dụng asyncHandler wrapper cho async route handlers
  • Verify error đang được throw (không chỉ log)

Example / Ví Dụ:

// ❌ Bad: Error not caught
app.get('/users/:id', async (req, res) => {
  const user = await userService.getUserById(req.params.id);
  res.json(user);
});

// ✅ Good: Error caught by middleware
app.get('/users/:id', asyncHandler(async (req, res) => {
  const user = await userService.getUserById(req.params.id);
  res.json(user);
}));

Error Messages Chung Chung Trong Production

Problem / Vấn Đề: Generic "Internal server error" được hiển thị ngay cả cho operational errors nên hiển thị messages cụ thể

Solution / Giải Pháp:

  • Kiểm tra isOperational flag được set đúng trên error instances
  • Verify error middleware xử lý tất cả error types đúng cách
  • Đảm bảo production environment check hoạt động đúng

Error Code Không Tìm Thấy

Problem / Vấn Đề: Error code không tìm thấy trong ErrorCode enum, gây vấn đề mapping

Solution / Giải Pháp:

  • Thêm error code vào ErrorCode enum theo naming convention ({CATEGORY}_{NUMBER})
  • Update ERROR_CODE_TO_STATUS mapping để bao gồm error code mới
  • Đảm bảo error code được sử dụng nhất quán trên các services

Stack Traces Bị Tiết Lộ

Problem / Vấn Đề: Stack traces hiển thị trong API responses, tiết lộ internal implementation details

Solution / Giải Pháp:

  • Đảm bảo production environment checks được đặt trong error middleware
  • Verify isProduction flag được set đúng
  • Filter stack traces và internal error details trong production responses

Prisma Errors Không Được Xử Lý

Problem / Vấn Đề: Prisma errors (như unique constraint violations) không được map sang HTTP errors phù hợp

Solution / Giải Pháp:

  • Thêm Prisma error code handling trong error middleware
  • Map common Prisma error codes (P2002, P2025, etc.) sang HTTP errors phù hợp
  • Tham khảo Prisma error code documentation để có mapping đầy đủ

Tài Nguyên