DevPath · Learn to code ESPTEN

Errors and robust validation

Custom error classes

Errors with meaning

Instead of throwing "bare" Errors, you define a custom error class that carries useful information, such as the HTTP status code.

class ApiError extends Error {
  constructor(message, statusCode) {
    super(message);          // sets this.message
    this.name = "ApiError";
    this.statusCode = statusCode;
  }
}

Since ApiError extends Error, it is still instanceof Error, so any code that already handles generic errors understands it, and it also exposes statusCode so the error middleware can pick the response.

if (!user) {
  throw new ApiError("User not found", 404);
}

Operational vs programmer errors

Distinguishing two families of errors helps decide how to respond:

A good rule: only operational errors should carry a message and status meant for the user; programmer errors are hidden behind a 500.

Examples

An ApiError is still an Error

class ApiError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.name = "ApiError";
    this.statusCode = statusCode;
  }
}

const e = new ApiError("Unauthorized", 401);
console.log(e.message);            // Unauthorized
console.log(e.statusCode);         // 401
console.log(e instanceof Error);   // true
Put this into practice

DevPath is a hands-on course: you read the theory here; in the app you put it into practice with exercises that really run, offline.

Start free in the app →
← The Express error middlewareRobust input validation →