Reputation: 509
as you know the default error interface in Fastify looks like
{
"statusCode": 400,
"error": "Bad Request",
"message": "Missing property blah-blah"
}
I really would like to be able to throw back something like
{
"statusCode": 400,
"error": "Bad Request",
"message": "Missing property blah-blah",
"myCustomError": "yo yo I am custom"
}
I tried multiple (really a lot!) combinations of using the setErrorHandler
and addHook("onError")
and I cannot return any custom error.
No matter what I do, the custom errors I throw from inside my handlers are somehow converted to this default interface and can't see to find a way around it. I also tried using the onSend
and onResponse
hooks, too. Nothing I tried worked out. :(
Is it even possible to return custom errors in Fastify v3? If not possible in v3, what about Fastify v4? Can anybody be so good to provide a code design which enables custom errors in Fastify?
Upvotes: 2
Views: 6270
Reputation: 455
To return a validation error with a custom message in fastify
you can use the ajv
and ajv-errors
packages.
import { fastify } from "fastify";
import Ajv from "ajv";
import AjvErrors from "ajv-errors";
const app = fastify();
const ajv = new Ajv({ allErrors: true });
AjvErrors(ajv);
async function createUser(req, reply) {
// create user logic
}
const createUserSchema = {
body: {
type: "object",
required: ["name"],
properties: {
name: {
type: "string",
},
},
additionalProperties: false,
errorMessage: {
required: {
name: "Please provide required name parameter",
},
},
},
};
app.route({
method: "POST",
url: "/user",
schema: createUserSchema,
handler: createUser,
validatorCompiler: ({ schema }) => ajv.compile(schema),
schemaErrorFormatter: (errors) => new Error(errors[0].message),
});
With the schemaErrorFormatter()
property, we specify the custom error formatter. Without this fastify
by default adds at the beginning of your custom message the place name where the error happened, like body
, querystring
, etc. Example and its test.
Upvotes: 0
Reputation: 12870
Whenever you return/throw an Error
, Fastify handles it with the default serializer that does not contain any additional properties.
To do so, you need to list the fields you want as output:
const statusCodes = require('http').STATUS_CODES
const fastify = require('fastify')({ logger: true })
fastify.get('/', async (request, reply) => {
const err = new Error('hello')
err.statusCode = 400
err.myCustomError = 'yo yo I am custom'
throw err
})
fastify.setErrorHandler(function (error, request, reply) {
if (error.myCustomError) {
reply
.status(error.statusCode || 500)
.send({
error: statusCodes[error.statusCode || 500],
message: error.message,
myCustomError: error.myCustomError,
statusCode: error.statusCode || 500
})
} else {
reply.send(error) // fallback to the default serializer
}
})
// {"error":"Bad Request","message":"hello","myCustomError":"yo yo I am custom","statusCode":400}
fastify.inject('/').then(res => console.log(res.payload))
This code works for fastify v3 and v4
Consider to read this article too
Upvotes: 7