fastify / fastify-sensible

Defaults for Fastify that everyone can agree on

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

How to override custom error handler

robinvdvleuten opened this issue · comments

I like the request methods this plugin adds, but how would like to handle the errors myself. How do I override the custom error handler? I've tried to add it after and before registering this plugin, but it never gets called;

fastify.setErrorHandler(function (error, request, reply) {
  // Never called here...
})

fastify.register(require('fastify-sensible'))

fastify.setErrorHandler(function (error, request, reply) {
  // Never called here...
})

Hi! The plugins are registered asynchronously, while the custom error handler is not.

This should fix your issue :)

fastify
  .register(require('fastify-sensible'))
  .after(() => {
    fastify.setErrorHandler(function (error, request, reply) {
      reply.send(error)
    })
  })

I've just added a test about this :)

test('Override error handler', t => {
t.plan(3)
const fastify = Fastify()
fastify
.register(Sensible)
.after(() => {
fastify.setErrorHandler(function (error, request, reply) {
reply.send(error)
})
})
fastify.get('/', (req, reply) => {
reply.send(new Error('kaboom'))
})
fastify.inject({
method: 'GET',
url: '/'
}, (err, res) => {
t.error(err)
t.strictEqual(res.statusCode, 500)
t.deepEqual(JSON.parse(res.payload), {
error: 'Internal Server Error',
message: 'kaboom',
statusCode: 500
})
})
})

Thanks, that works indeed! Still trying to get my head around Fastify's async plugin structure 🙃

No problem, if you have some question open an issue in fastify/help :)

commented

Reading your case I was wondering : is it possible to specify mutliple error handlers (via setErrorHandler(...) inside plugins and on main fastify instance) and deliberately pass on to the next handler ?
e.g : imagine one plugin fastify-boom and another one fastify-joi : in the first one it handles the error only if error.isBoom otherwise it just ignores and let the second one handles only if error.isJoi, otherwise falls back to the default error handler.
I tried already but it seems no matter which error handler get called, it has to reply.send(...) something or it get stucked there.

Hi @Roms1383!
No, you can't declare a "chain" of error handlers, but you can build it inside a single one!
Take a look at how we built our hook runner ;)
https://github.com/fastify/fastify/blob/c9f6ba92788c1ef70fb24ab4bb34a5d58f433dde/lib/hooks.js#L60-L84

commented

Ha ! That's what I ended up doing ^^
But wouldn't it be a cool feature in the future ?

Feel free to open a feature request in the main repo, where we can discuss more :)

I think we should remove the error handler from this module, or provide an option to disable it.

I have a follow-up question regarding overriding the custom error handler.

I´m using i18-next and want to customize my error messages in a custom setErrorHandler. Here are my plugin registration from top to bottom.

app.register(i18nextMiddleware.plugin, { i18next });

By registering this plugin I´ll get the t() method attached to the request object (I can access this in preHandler and handler hooks without any problem).

app.register(routes, { prefix: '/api/v1' });

app.setErrorHandler((error, request, reply) => { console.log('request.t: ', request.t); reply.send(error); });

Once I generate an error (e.g. validation error) this error is passed to my custom handler where I want to localize the error message with the t() method of the registered i18next plugin. This is were I get undefined for calling request.t() as it is not registered yet is suppose.
I´ve also tried to do the setErrorHandler in an after call of the i18next registering part, as the setErrorHandler is sync and registering async.

Any tips for solving the issue? Thank you very much in advance!