SkillByAIOpen interactive version →

Lesson 21 / 32

Error Handling

Throw errors in async handlers, define custom error classes and control error responses.

Error handling strategy

Throw errors in route handlers; Fastify's built-in error handler catches them and returns appropriate status codes and responses.

Custom error class

Define a custom error class to control status codes and payloads.

class AppError extends Error {
  constructor(message, statusCode = 500) {
    super(message);
    this.statusCode = statusCode;
  }
}

fastify.get('/users/:id', async (req) => {
  const user = await findUser(req.params.id);
  if (!user) {
    throw new AppError('User not found', 404);
  }
  return user;
});

fastify.setErrorHandler((err, req, reply) => {
  const statusCode = err.statusCode || 500;
  reply.status(statusCode).send({ error: err.message });
});

Async error handling

Fastify automatically catches errors thrown in async handlers—no need for try/catch wrappers.

A custom error handler

setErrorHandler catches errors thrown in handlers and hooks.

  • error.statusCode is set by reply.code or validation failures.
  • Return a consistent JSON shape.
const fastify = require('fastify')();

fastify.setErrorHandler((error, request, reply) => {
  reply.code(error.statusCode || 500).send({
    ok: false,
    message: error.message
  });
});

fastify.get('/boom', async () => {
  throw new Error('kaboom');
});

Quick check

Quick check: What status does Fastify use for an uncaught `throw new Error('x')` in a handler by default?

  • 400
  • 500
  • 200
Answer

500 — Errors without a statusCode become 500 Internal Server Error.