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()) +})