Errors
Errors
Error Handling In Node.js
Uncaught Errors
In Node.js, uncaught errors are likely to cause memory leaks, file descriptor leaks, and other major production issues. Domains were a failed attempt to fix this.
Given that it is not possible to process all uncaught errors sensibly, the best way to deal with them is to crash.
Catching Errors In Promises
If you are using promises, you should attach a .catch()
handler synchronously.
Errors In Fastify
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.
Errors In Input Data
Most errors are a result of unexpected input data, so we recommend validating your input data against a JSON schema.
Catching Uncaught Errors In Fastify
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.
To customize this behavior you should use
setErrorHandler
.
Errors In Fastify Lifecycle Hooks And A Custom Error Handler
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.
When a custom error handler has been defined through
setErrorHandler
, the custom error handler will
receive the error passed to the done()
callback (or through other supported
automatic error handling mechanisms). If setErrorHandler
has been used
multiple times to define multiple handlers, the error will be routed to the most
precedent handler defined within the error encapsulation
context. Error handlers are fully encapsulated, so a
setErrorHandler
call within a plugin will limit the error handler to that
plugin's context.
The root error handler is Fastify's generic error handler. This error handler
will use the headers and status code in the Error
object, if they exist. The
headers and status code will not be automatically set if a custom error handler
is provided.
Some things to consider in your custom error handler:
-
you can
reply.send(data)
, which will behave as it would in regular route handlers- objects are serialized, 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 serialized, triggering the
-
You can throw a new error in your custom error handler - errors (new error or the received error parameter re-thrown) - will call the parent
errorHandler
.onError
hook will be triggered once only for the first error being thrown.- 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)
Fastify Error Codes
You can access errorCodes
for mapping:
// ESM
import { errorCodes } from 'fastify'
// CommonJs
const errorCodes = require('fastify').errorCodes
For example:
const Fastify = require('./fastify')
// Instantiate the framework
const fastify = Fastify({
logger: true
})
// Declare a route
fastify.get('/', function (request, reply) {
reply.code('bad status code').send({ hello: 'world' })
})
fastify.setErrorHandler(function (error, request, reply) {
if (error instanceof Fastify.errorCodes.FST_ERR_BAD_STATUS_CODE) {
// Log error
this.log.error(error)
// Send error response
reply.status(500).send({ ok: false })
} else {
// fastify will use parent error handler to handle this
reply.send(error)
}
})
// Run the server!
fastify.listen({ port: 3000 }, function (err, address) {
if (err) {
fastify.log.error(err)
process.exit(1)
}
// Server is now listening on ${address}
})
FST_ERR_NOT_FOUND
404 Not Found.
FST_ERR_OPTIONS_NOT_OBJ
Fastify options must be an object.
FST_ERR_QSP_NOT_FN
QueryStringParser option should be a function.
FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN
SchemaController.bucket option should be a function.
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN
SchemaErrorFormatter option should be a non async function.
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ
ajv.customOptions option should be an object.
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR
ajv.plugins option should be an array.
FST_ERR_VERSION_CONSTRAINT_NOT_STR
Version constraint should be a string.
FST_ERR_CTP_ALREADY_PRESENT
The parser for this content type was already registered.
FST_ERR_CTP_INVALID_TYPE
The Content-Type
should be a string.
FST_ERR_CTP_EMPTY_TYPE
The content type cannot be an empty string.
FST_ERR_CTP_INVALID_HANDLER
An invalid handler was passed for the content type.
FST_ERR_CTP_INVALID_PARSE_TYPE
The provided parse type is not supported. Accepted values are string
or
buffer
.
FST_ERR_CTP_BODY_TOO_LARGE
The request body is larger than the provided limit.
This setting can be defined in the Fastify server instance:
bodyLimit
FST_ERR_CTP_INVALID_MEDIA_TYPE
The received media type is not supported (i.e. there is no suitable
Content-Type
parser for it).
FST_ERR_CTP_INVALID_CONTENT_LENGTH
Request body size did not match Content-Length
.
FST_ERR_CTP_EMPTY_JSON_BODY
Body cannot be empty when content-type is set to application/json
.
FST_ERR_CTP_INSTANCE_ALREADY_STARTED
Fastify is already started.
FST_ERR_INSTANCE_ALREADY_LISTENING
Fastify instance is already listening.
FST_ERR_DEC_ALREADY_PRESENT
A decorator with the same name is already registered.