Bỏ qua, đến nội dung

Câu hỏi thường gặp (FAQ) — Error Handler

Sử dụng

Làm sao xem chi tiết lỗi 500?

Lỗi 500 (Internal Server Error) chỉ hiển thị thông báo chung trên client để bảo mật. Chi tiết lỗi bao gồm stack trace và cause được ghi trong log server.

Cách xem:

  1. Kiểm tra log file: thường nằm tại logs/ hoặc stdout
  2. Tìm dòng có method: 'error-handler'
  3. Xem trường err (stack trace) và cause để hiểu nguyên nhân

Có thể tùy chỉnh thông báo lỗi không?

Có. Có hai cách:

  1. Đăng ký custom handler trong plugin của bạn:
typescript
const errorHandlerPlugin = this.app.pm.get('error-handler');
errorHandlerPlugin.errorHandler.register(
  (err) => err.code === 'MY_CUSTOM_ERROR',
  (err, ctx) => {
    ctx.status = 400;
    ctx.body = {
      errors: [{ message: ctx.i18n.t('Thông báo lỗi tùy chỉnh') }],
    };
  },
);
  1. Sử dụng i18n — thông báo lỗi validation tự động được dịch qua hệ thống i18n. Thêm bản dịch vào namespace error-handler.

Thứ tự handler có quan trọng không?

Có. Handler được duyệt theo thứ tự đăng ký. Handler đầu tiên có guard trả về true sẽ được sử dụng, các handler sau bị bỏ qua. Vì vậy:

  • Đăng ký handler cụ thể trước handler chung
  • Handler core (Sequelize, SQL) được đăng ký trong beforeLoad() của plugin

Tại sao lỗi validation hiển thị tên trường bằng tiếng Anh?

Plugin tìm tên trường theo thứ tự:

  1. uiSchema.title trong collection schema (thường là template i18n {{t("...")}})
  2. Tên trường gốc (fallback)

Nếu collection chưa có uiSchema.title hoặc thiếu bản dịch, tên trường tiếng Anh sẽ hiển thị. Kiểm tra:

  • Collection field có uiSchema.title không
  • Namespace i18n lm-collectionsclient có bản dịch không

Có thể tắt plugin error-handler không?

Không nên. Đây là plugin core. Nếu tắt:

  • Lỗi sẽ trả về stack trace cho client (rủi ro bảo mật)
  • Các plugin khác đã đăng ký handler sẽ không hoạt động
  • Response lỗi không được chuẩn hóa

Lỗi thường gặp

Client nhận lỗi không rõ ràng?

Nguyên nhân:

  • Lỗi thuộc loại không có handler cụ thể — default handler chỉ trả err.message
  • Hoặc lỗi là 500 (server error) — chỉ trả thông báo chung

Cách khắc phục:

  1. Xem log server để biết chi tiết
  2. Nếu cần thông báo rõ ràng hơn, đăng ký custom handler cho loại lỗi đó

Lỗi SQL hiển thị "Invalid SQL syntax" — làm sao biết lỗi gì?

Plugin cố ý ẩn chi tiết SQL error để không lộ cấu trúc database. Xem chi tiết trong log server:

ctx.log.error(err.message, { method: 'error-handler', err: err.stack })

Lỗi "Invalid SQL column or table reference"?

Collection hoặc field bị xóa/đổi tên nhưng code/UI vẫn tham chiếu đến tên cũ. Kiểm tra:

  • Collection còn tồn tại trong database không
  • Field được tham chiếu có đúng tên không
  • Nếu dùng external data source, thử Refresh schema

Validation error không hiển thị đầy đủ các trường lỗi?

Plugin chỉ xử lý SequelizeValidationErrorSequelizeUniqueConstraintError. Validation khác (ví dụ: custom validation trong action) cần tự throw error với format phù hợp hoặc đăng ký handler riêng.

Dành cho nhà phát triển

Làm sao throw error đúng cách trong custom action?

typescript
// Cách 1: Sử dụng ctx.throw (Koa standard)
ctx.throw(400, 'Validation failed');

// Cách 2: Throw Error với statusCode
const err = new Error('Custom error message');
err.statusCode = 400;
throw err;

// Cách 3: Throw với cause
throw new Error('Operation failed', {
  cause: new Error('Database connection timeout'),
});

Làm sao đăng ký handler cho lỗi từ API bên ngoài?

typescript
errorHandlerPlugin.errorHandler.register(
  (err) => err.cause?.errorContent !== undefined,
  (err, ctx) => {
    ctx.status = 500;
    ctx.body = {
      errors: [{ message: String(err.cause.errorContent) }],
    };
  },
);

Có cần xử lý lỗi async trong handler?

Middleware error handler tự động bắt lỗi async (nhờ try-catch bao quanh await next()). Bạn chỉ cần throw error — không cần wrapper bổ sung.