diff --git a/docs/Reference/Errors.md b/docs/Reference/Errors.md
index c1149c7e02..070029e2d1 100644
--- a/docs/Reference/Errors.md
+++ b/docs/Reference/Errors.md
@@ -92,6 +92,7 @@
- [FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE](#fst_err_plugin_not_present_in_instance)
- [FST_ERR_VALIDATION](#fst_err_validation)
- [FST_ERR_LISTEN_OPTIONS_INVALID](#fst_err_listen_options_invalid)
+ - [FST_ERR_ERROR_HANDLER_NOT_FN](#fst_err_error_handler_not_fn)
### Error Handling In Node.js
@@ -361,4 +362,5 @@ but the body is being consumed. | Make sure you don't consume the `Response.body
| FST_ERR_PLUGIN_NOT_PRESENT_IN_INSTANCE | The decorator is not present in the instance. | - | [#4554](https://github.com/fastify/fastify/pull/4554) |
| FST_ERR_VALIDATION | The Request failed the payload validation. | Check the request payload. | [#4824](https://github.com/fastify/fastify/pull/4824) |
| FST_ERR_LISTEN_OPTIONS_INVALID | Invalid listen options. | Check the listen options. | [#4886](https://github.com/fastify/fastify/pull/4886) |
+| FST_ERR_ERROR_HANDLER_NOT_FN | Error Handler must be a function | Provide a function to `setErrorHandler`. | [#5317](https://github.com/fastify/fastify/pull/5317) |
diff --git a/fastify.js b/fastify.js
index a7f6058a16..d0030fbd75 100644
--- a/fastify.js
+++ b/fastify.js
@@ -71,7 +71,8 @@ const {
FST_ERR_INSTANCE_ALREADY_LISTENING,
FST_ERR_REOPENED_CLOSE_SERVER,
FST_ERR_ROUTE_REWRITE_NOT_STR,
- FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN
+ FST_ERR_SCHEMA_ERROR_FORMATTER_NOT_FN,
+ FST_ERR_ERROR_HANDLER_NOT_FN
} = errorCodes
const { buildErrorHandler } = require('./lib/error-handler.js')
@@ -844,6 +845,10 @@ function fastify (options) {
function setErrorHandler (func) {
throwIfAlreadyStarted('Cannot call "setErrorHandler"!')
+ if (typeof func !== 'function') {
+ throw new FST_ERR_ERROR_HANDLER_NOT_FN()
+ }
+
this[kErrorHandler] = buildErrorHandler(this[kErrorHandler], func.bind(this))
return this
}
diff --git a/lib/errors.js b/lib/errors.js
index 90ae13cb76..e64f73cdfd 100644
--- a/lib/errors.js
+++ b/lib/errors.js
@@ -64,6 +64,12 @@ const codes = {
500,
TypeError
),
+ FST_ERR_ERROR_HANDLER_NOT_FN: createError(
+ 'FST_ERR_ERROR_HANDLER_NOT_FN',
+ 'Error Handler must be a function',
+ 500,
+ TypeError
+ ),
/**
* ContentTypeParser
diff --git a/test/internals/errors.test.js b/test/internals/errors.test.js
index eaa6426364..0f47c45f53 100644
--- a/test/internals/errors.test.js
+++ b/test/internals/errors.test.js
@@ -5,7 +5,7 @@ const errors = require('../../lib/errors')
const { readFileSync } = require('node:fs')
const { resolve } = require('node:path')
-test('should expose 79 errors', t => {
+test('should expose 80 errors', t => {
t.plan(1)
const exportedKeys = Object.keys(errors)
let counter = 0
@@ -14,11 +14,11 @@ test('should expose 79 errors', t => {
counter++
}
}
- t.equal(counter, 79)
+ t.equal(counter, 80)
})
test('ensure name and codes of Errors are identical', t => {
- t.plan(79)
+ t.plan(80)
const exportedKeys = Object.keys(errors)
for (const key of exportedKeys) {
if (errors[key].name === 'FastifyError') {
@@ -827,8 +827,18 @@ test('FST_ERR_LISTEN_OPTIONS_INVALID', t => {
t.ok(error instanceof TypeError)
})
+test('FST_ERR_ERROR_HANDLER_NOT_FN', t => {
+ t.plan(5)
+ const error = new errors.FST_ERR_ERROR_HANDLER_NOT_FN()
+ t.equal(error.name, 'FastifyError')
+ t.equal(error.code, 'FST_ERR_ERROR_HANDLER_NOT_FN')
+ t.equal(error.message, 'Error Handler must be a function')
+ t.equal(error.statusCode, 500)
+ t.ok(error instanceof TypeError)
+})
+
test('Ensure that all errors are in Errors.md TOC', t => {
- t.plan(79)
+ t.plan(80)
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
const exportedKeys = Object.keys(errors)
@@ -840,7 +850,7 @@ test('Ensure that all errors are in Errors.md TOC', t => {
})
test('Ensure that non-existing errors are not in Errors.md TOC', t => {
- t.plan(79)
+ t.plan(80)
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
const matchRE = / {4}- \[([A-Z0-9_]+)\]\(#[a-z0-9_]+\)/g
@@ -853,7 +863,7 @@ test('Ensure that non-existing errors are not in Errors.md TOC', t => {
})
test('Ensure that all errors are in Errors.md documented', t => {
- t.plan(79)
+ t.plan(80)
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
const exportedKeys = Object.keys(errors)
@@ -865,7 +875,7 @@ test('Ensure that all errors are in Errors.md documented', t => {
})
test('Ensure that non-existing errors are not in Errors.md documented', t => {
- t.plan(79)
+ t.plan(80)
const errorsMd = readFileSync(resolve(__dirname, '../../docs/Reference/Errors.md'), 'utf8')
const matchRE = /([0-9a-zA-Z_]+)<\/a>/g
diff --git a/test/set-error-handler.test.js b/test/set-error-handler.test.js
new file mode 100644
index 0000000000..737fd02bb8
--- /dev/null
+++ b/test/set-error-handler.test.js
@@ -0,0 +1,13 @@
+'use strict'
+
+const t = require('tap')
+const test = t.test
+const Fastify = require('..')
+const { FST_ERR_ERROR_HANDLER_NOT_FN } = require('../lib/errors')
+
+test('setErrorHandler should throw an error if the handler is not a function', t => {
+ t.plan(1)
+ const fastify = Fastify()
+
+ t.throws(() => fastify.setErrorHandler('not a function'), new FST_ERR_ERROR_HANDLER_NOT_FN())
+})