In Node.js, uncaught errors are likely to cause memory leaks, file descriptor leaks and other major production issues. Domains were introduced to try fix this issue, but did not.
Given that it is not possible to process all uncaught errors sensibly, the best way to deal with them is to crash.
In Node.js, unhandled promise rejections (that is, without a .catch()
handler) can also cause memory and file descriptor leaks. While unhandledRejection
is deprecated in Node.js, unhandled rejections will not throw, and still potentially leak. You should use a module like make-promises-safe
to ensure unhandled rejections always throw.
If you are using promises, you should attach a .catch()
handler synchronously.
Fastify follows an all-or-nothing approach and aims to be lean and optimal as much as possible. The developer is responsible for making sure that the errors are handled properly.
Most errors are a result of unexpected input data, so we recommend specifying a JSON.schema validation for your input data.
Fastify tries to catch as many uncaught errors as it can without hindering performance. This includes:
- synchronous routes, e.g.
app.get('/', () => { throw new Error('kaboom') })
async
routes, e.g.app.get('/', async () => { throw new Error('kaboom') })
The error in both cases will be caught safely and routed to Fastify's default error handler for a generic 500 Internal Server Error
response.
For customizing this behaviour, you should use setErrorHandler
.
From the Hooks documentation:
If you get an error during the execution of your hook, just pass it to
done()
and Fastify will automatically close the request and send the appropriate error code to the user.
If you have defined a custom error handler for using setErrorHandler
the error will be routed there, otherwise it will be routed to Fastify’s generic error handler.
Some things to consider in your custom error handler:
-
you can
reply.send(data)
which will be behave as it would be in regular route handlers- objects are serialised, triggering the
preSerialization
lifecycle hook if you have one defined - strings, buffers, and streams are sent to the client, with appropriate headers (no serialization)
- objects are serialised, triggering the
-
You can throw a new error in your custom error handler
- errors (new error or the received error parameter re-thrown) - will trigger the
onError
lifecycle hook and send the error to the user - an error will not be triggered twice from a lifecycle hook - Fastify internally monitors the error invocation to avoid infinite loops for errors thrown in the reply phases of the lifecycle. (those after the route handler)
- errors (new error or the received error parameter re-thrown) - will trigger the
The router received an invalid url.
The parser for this content type was already registered.
The Content-Type
should be a string.
The content type cannot be an empty string.
An invalid handler was passed for the content type.
The provided parse type is not supported. Accepted values are string
or buffer
.
The request body is larger than the provided limit.
The received media type is not supported (i.e. there is no suitable Content-Type
parser for it).
Request body size did not match Content-Length.
A decorator with the same name is already registered.
The decorator cannot be registered due to a missing dependency.
The hook name must be a string.
The hook callback must be a function.
The logger accepts either a 'stream'
or a 'file'
as the destination.
A response was already sent.
You cannot use send
inside the onError
hook.
Reply payload can either be a string
or a Buffer
.
The schema provided does not have $id
property.
A schema with the same $id
already exists.
The JSON schema provided for validation to a route is not valid.
The JSON schema provided for serialization of a route response is not valid.
A promise may not be fulfilled with 'undefined' when statusCode is not 204.
Undefined error has occurred.