Version: latest (v5.8.x)
Errors
Table of contents
- Errors
Error Handling In Node.js
Uncaught Errors
In Node.js, uncaught errors can 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
When using promises, attach a .catch() handler synchronously.
Errors In Fastify
Fastify follows an all-or-nothing approach and aims to be lean and optimal. The developer is responsible for ensuring errors are handled properly.
Errors In Input Data
Most errors result from unexpected input data, so it is recommended to validate input data against a JSON schema.
Catching Uncaught Errors In Fastify
Fastify tries to catch as many uncaught errors as possible without hindering performance. This includes:
- synchronous routes, e.g.
app.get('/', () => { throw new Error('kaboom') }) asyncroutes, e.g.app.get('/', async () => { throw new Error('kaboom') })
In both cases, the error will be caught safely and routed to Fastify's default error handler, resulting in a generic 500 Internal Server Error response.
To customize this behavior, 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 is defined through setErrorHandler, it will receive the error passed to the done() callback or through other supported automatic error handling mechanisms. If setErrorHandler is used multiple times, the error will be routed to the most precedent handler 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.
The following should be considered when using a custom error handler:
-
reply.send(data)behaves as in regular route handlers- objects are serialized, triggering the
preSerializationlifecycle hook if defined - strings, buffers, and streams are sent to the client with appropriate headers (no serialization)
- objects are serialized, triggering the
-
Throwing a new error in a custom error handler will call the parent
errorHandler.- The
onErrorhook will be triggered once for the first error thrown - An error will not be triggered twice from a lifecycle hook. Fastify internally monitors error invocation to avoid infinite loops for errors thrown in the reply phases of the lifecycle (those after the route handler)
- The
When using Fastify's custom error handling through setErrorHandler, be aware of how errors are propagated between custom and default error handlers.
If a plugin's error handler re-throws an error that is not an instance of Error, it will not propagate to the parent context error handler. Instead, it will be caught by the default error handler. This can be seen in the /bad route of the example below.
To ensure consistent error handling, throw instances of Error. For example, replace throw 'foo' with throw new Error('foo') in the /bad route to ensure errors propagate through the custom error handling chain as intended. This practice helps avoid potential pitfalls when working with custom error handling in Fastify.
For example:
const Fastify = require('fastify')// Instantiate the frameworkconst fastify = Fastify({ logger: true})// Register parent error handlerfastify.setErrorHandler((error, request, reply) => { reply.status(500).send({ ok: false })})fastify.register((app, options, next) => { // Register child error handler fastify.setErrorHandler((error, request, reply) => { throw error }) fastify.get('/bad', async () => { // Throws a non-Error type, 'bar' throw 'foo' }) fastify.get('/good', async () => { // Throws an Error instance, 'bar' throw new Error('bar') }) next()})// Run the serverfastify.listen({ port: 3000 }, function (err, address) { if (err) { fastify.log.error(err) process.exit(1) } // Server is listening at ${address}})
Fastify Error Codes
You can access errorCodes for mapping:
// ESMimport { errorCodes } from 'fastify'// CommonJSconst errorCodes = require('fastify').errorCodes
For example:
const Fastify = require('fastify')// Instantiate the frameworkconst fastify = Fastify({ logger: true})// Declare a routefastify.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}})
Below is a table with all the error codes used by Fastify.
Code
Description
How to solve
Discussion
FST_ERR_NOT_FOUND
404 Not Found
-
FST_ERR_OPTIONS_NOT_OBJ
Fastify options wrongly specified.
Fastify options should be an object.
FST_ERR_QSP_NOT_FN
QueryStringParser wrongly specified.
QueryStringParser option should be a function.
FST_ERR_SCHEMA_CONTROLLER_BUCKET_OPT_NOT_FN
SchemaController.bucket wrongly specified.
SchemaController.bucket option should be a function.
FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN
SchemaErrorFormatter option wrongly specified.
SchemaErrorFormatter option should be a non async function.
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_OBJ
ajv.customOptions wrongly specified.
ajv.customOptions option should be an object.
FST_ERR_AJV_CUSTOM_OPTIONS_OPT_NOT_ARR
ajv.plugins option wrongly specified.
ajv.plugins option should be an array.
FST_ERR_CTP_ALREADY_PRESENT
The parser for this content type was already registered.
Use a different content type or delete the already registered parser.
FST_ERR_CTP_INVALID_TYPE
Content-Type wrongly specified
The Content-Type should be a string.
FST_ERR_CTP_EMPTY_TYPE
Content-Type is an empty string.
Content-Type cannot be an empty string.
FST_ERR_CTP_INVALID_HANDLER
Invalid handler for the content type.
Use a different handler.
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.
Increase the limit in the Fastify server instance setting: 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).
Use a different content type.
FST_ERR_CTP_INVALID_CONTENT_LENGTH
Request body size did not match Content-Length.
Check the request body size and the Content-Length header.
FST_ERR_CTP_EMPTY_JSON_BODY
Body is not valid JSON but content-type is set to application/json.
Check if the request body is valid JSON.
FST_ERR_CTP_INVALID_JSON_BODY
Body cannot be empty when content-type is set to application/json.
Check the request body.
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.
Use a different decorator name.
FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
The dependencies of decorator must be of type Array.
Use an array for the dependencies.
FST_ERR_DEC_MISSING_DEPENDENCY
The decorator cannot be registered due to a missing dependency.
Register the missing dependency.
FST_ERR_DEC_AFTER_START
The decorator cannot be added after start.
Add the decorator before starting the server.
FST_ERR_DEC_REFERENCE_TYPE
The decorator cannot be a reference type.
Define the decorator with a getter/setter interface or an empty decorator with a hook.
FST_ERR_DEC_UNDECLARED
An attempt was made to access a decorator that has not been declared.
Declare the decorator before using it.
FST_ERR_HOOK_INVALID_TYPE
The hook name must be a string.
Use a string for the hook name.
FST_ERR_HOOK_INVALID_HANDLER
The hook callback must be a function.
Use a function for the hook callback.
FST_ERR_HOOK_INVALID_ASYNC_HANDLER
Async function has too many arguments. Async hooks should not use the done argument.
Remove the done argument from the async hook.
FST_ERR_HOOK_NOT_SUPPORTED
The hook is not supported.
Use a supported hook.
FST_ERR_MISSING_MIDDLEWARE
You must register a plugin for handling middlewares, visit Middleware for more info.
Register a plugin for handling middlewares.
FST_ERR_HOOK_TIMEOUT
A callback for a hook timed out.
Increase the timeout for the hook.
FST_ERR_LOG_INVALID_DESTINATION
The logger does not accept the specified destination.
Use a 'stream' or a 'file' as the destination.
FST_ERR_LOG_INVALID_LOGGER
The logger should have all these methods: 'info', 'error', 'debug', 'fatal', 'warn', 'trace', 'child'.
Use a logger with all the required methods.
FST_ERR_LOG_INVALID_LOGGER_INSTANCE
The loggerInstance only accepts a logger instance, not a configuration object.
To pass a configuration object, use 'logger' instead.
FST_ERR_LOG_INVALID_LOGGER_CONFIG
The logger option only accepts a configuration object, not a logger instance.
To pass an instance, use 'loggerInstance' instead.
FST_ERR_LOG_LOGGER_AND_LOGGER_INSTANCE_PROVIDED
You cannot provide both 'logger' and 'loggerInstance'.
Please provide only one option.
FST_ERR_REP_INVALID_PAYLOAD_TYPE
Reply payload can be either a string or a Buffer.
Use a string or a Buffer for the payload.
FST_ERR_REP_RESPONSE_BODY_CONSUMED
Using Response as reply payload, but the body is being consumed.
Make sure you don't consume the Response.body
FST_ERR_REP_READABLE_STREAM_LOCKED
Using ReadableStream as reply payload, but locked with another reader.
Make sure you don't call the Readable.getReader before sending or release lock with reader.releaseLock() before sending.
FST_ERR_REP_ALREADY_SENT
A response was already sent.
-
FST_ERR_REP_SENT_VALUE
The only possible value for reply.sent is true.
-
FST_ERR_SEND_INSIDE_ONERR
You cannot use send inside the onError hook.
-
FST_ERR_SEND_UNDEFINED_ERR
Undefined error has occurred.
-
FST_ERR_BAD_STATUS_CODE
The status code is not valid.
Use a valid status code.
FST_ERR_BAD_TRAILER_NAME
Called reply.trailer with an invalid header name.
Use a valid header name.
FST_ERR_BAD_TRAILER_VALUE
Called reply.trailer with an invalid type. Expected a function.
Use a function.
FST_ERR_FAILED_ERROR_SERIALIZATION
Failed to serialize an error.
-
FST_ERR_MISSING_SERIALIZATION_FN
Missing serialization function.
Add a serialization function.
FST_ERR_MISSING_CONTENTTYPE_SERIALIZATION_FN
Missing Content-Type serialization function.
Add a serialization function.
FST_ERR_REQ_INVALID_VALIDATION_INVOCATION
Invalid validation invocation. Missing validation function for HTTP part nor schema provided.
Add a validation function.
FST_ERR_SCH_MISSING_ID
The schema provided does not have $id property.
Add a $id property.
FST_ERR_SCH_ALREADY_PRESENT
A schema with the same $id already exists.
Use a different $id.
FST_ERR_SCH_CONTENT_MISSING_SCHEMA
A schema is missing for the corresponding content type.
Add a schema.
FST_ERR_SCH_DUPLICATE
Schema with the same attribute already present!
Use a different attribute.
FST_ERR_SCH_VALIDATION_BUILD
The JSON schema provided for validation to a route is not valid.
Fix the JSON schema.
FST_ERR_SCH_SERIALIZATION_BUILD
The JSON schema provided for serialization of a route response is not valid.
Fix the JSON schema.
FST_ERR_SCH_RESPONSE_SCHEMA_NOT_NESTED_2XX
Response schemas should be nested under a valid status code (2XX).
Use a valid status code.
FST_ERR_INIT_OPTS_INVALID
Invalid initialization options.
Use valid initialization options.
FST_ERR_FORCE_CLOSE_CONNECTIONS_IDLE_NOT_AVAILABLE
Cannot set forceCloseConnections to idle as your HTTP server does not support closeIdleConnections method.
Use a different value for forceCloseConnections.
FST_ERR_DUPLICATED_ROUTE
The HTTP method already has a registered controller for that URL.
Use a different URL or register the controller for another HTTP method.
FST_ERR_BAD_URL
The router received an invalid URL.
Use a valid URL.
FST_ERR_ASYNC_CONSTRAINT
The router received an error when using asynchronous constraints.
-
FST_ERR_INVALID_URL
URL must be a string.
Use a string for the URL.
FST_ERR_ROUTE_OPTIONS_NOT_OBJ
Options for the route must be an object.
Use an object for the route options.
FST_ERR_ROUTE_DUPLICATED_HANDLER
Duplicate handler for the route is not allowed.
Use a different handler.
FST_ERR_ROUTE_HANDLER_NOT_FN
Handler for the route must be a function.
Use a function for the handler.
FST_ERR_ROUTE_MISSING_HANDLER
Missing handler function for the route.
Add a handler function.
FST_ERR_ROUTE_METHOD_INVALID
Method is not a valid value.
Use a valid value for the method.
FST_ERR_ROUTE_METHOD_NOT_SUPPORTED
Method is not supported for the route.
Use a supported method.
FST_ERR_ROUTE_BODY_VALIDATION_SCHEMA_NOT_SUPPORTED
Body validation schema route is not supported.
Use a different different method for the route.
FST_ERR_ROUTE_BODY_LIMIT_OPTION_NOT_INT
bodyLimit option must be an integer.
Use an integer for the bodyLimit option.
FST_ERR_HANDLER_TIMEOUT
Request timed out.
Increase the handlerTimeout option or optimize the handler.
-
FST_ERR_ROUTE_HANDLER_TIMEOUT_OPTION_NOT_INT
handlerTimeout option must be a positive integer.
Use a positive integer for the handlerTimeout option.
-
FST_ERR_ROUTE_REWRITE_NOT_STR
rewriteUrl needs to be of type string.
Use a string for the rewriteUrl.
FST_ERR_REOPENED_CLOSE_SERVER
Fastify has already been closed and cannot be reopened.
-
FST_ERR_REOPENED_SERVER
Fastify is already listening.
-
FST_ERR_PLUGIN_VERSION_MISMATCH
Installed Fastify plugin mismatched expected version.
Use a compatible version of the plugin.
FST_ERR_PLUGIN_CALLBACK_NOT_FN
Callback for a hook is not a function.
Use a function for the callback.
FST_ERR_PLUGIN_NOT_VALID
Plugin must be a function or a promise.
Use a function or a promise for the plugin.
FST_ERR_ROOT_PLG_BOOTED
Root plugin has already booted.
-
FST_ERR_PARENT_PLUGIN_BOOTED
Impossible to load plugin because the parent (mapped directly from avvio)
-
FST_ERR_PLUGIN_TIMEOUT
Plugin did not start in time.
Increase the timeout for the plugin.
FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE
The decorator is not present in the instance.
-
FST_ERR_PLUGIN_INVALID_ASYNC_HANDLER
The plugin being registered mixes async and callback styles.
-
FST_ERR_VALIDATION
The Request failed the payload validation.
Check the request payload.
FST_ERR_LISTEN_OPTIONS_INVALID
Invalid listen options.
Check the listen options.
FST_ERR_ERROR_HANDLER_NOT_FN
Error Handler must be a function
Provide a function to setErrorHandler.