Skip to main content

Fastify

Register a setErrorHandler that maps @gentleduck/error instances to JSON responses, matching Fastify's single-handler error model.

Overview

Fastify routes every error, whether thrown, rejected, or passed to a callback, through one registered handler, set via setErrorHandler. There is no middleware chain to order; the handler you set is the only one that runs.

Full runnable example: examples/fastify.

Error handler

import Fastify from 'fastify'
import { AppError } from './errors'

const app = Fastify()

app.setErrorHandler((err, _req, reply) => {
  if (err instanceof AppError) {
    reply.status(err.status).send(err.toJSON())
    return
  }
  app.log.error(err)
  reply.status(500).send({ ok: false, error: { code: 'INTERNAL', status: 500 } })
})

Throwing from a route

Fastify awaits an async handler's returned promise natively, so a thrown AppError reaches setErrorHandler with no extra wiring:

import { throwAppError } from './errors'

app.get('/widgets/:id', async (req) => {
  const { id } = req.params as { id: string }
  const widget = await db.widgets.findById(id)
  if (!widget) throwAppError('NOT_FOUND', { resource: 'widget', id })
  return widget
})