fastify-type-provider-zod
fastify-type-provider-zod copied to clipboard
custom error handler unable to check for instanceof ResponseValidationError
I am writing my own error handler for Fastify and want to intercept ResponseValidationError
s similar to the code example here: https://github.com/turkerdev/fastify-type-provider-zod/issues/26#issuecomment-1516147720. I'm using TypeScript.
When I try to check for the error using error instanceof ResponseValidationError
I get false
.
error.name === 'ResponseValidationError'
is true so it is an instance of ResponseValidationError: https://github.com/turkerdev/fastify-type-provider-zod/blob/85675fad44c7679622d80fb1925f5901cc2f57f8/src/index.ts#L122
Am I missing something here? If the name is set correctly I'd expect the instanceof
check to work.
My overall goal is to respond normally on response validation errors and log instead of returning errors to the client.
Code to reproduce below.
import { FastifyInstance } from 'fastify'
import {
ResponseValidationError,
ZodTypeProvider,
} from 'fastify-type-provider-zod'
import z, { ZodError } from 'zod'
type Params = {
id: string
}
export default async function routes(fastify: FastifyInstance) {
fastify.get('/', async () => ({ hello: 'world' }))
fastify.withTypeProvider<ZodTypeProvider>().get<{ Params: Params }>(
'/session/:id',
{
schema: {
params: z.object({
id: z.string().max(5),
}),
response: {
200: z.number(),
},
},
},
async (request, reply) => {
const { id } = request.params
reply.send({ hello: id })
},
)
fastify.setErrorHandler(function (error, request, reply) {
fastify.log.warn(error)
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
if (error instanceof ZodError) {
console.log('ZodError')
}
if (error instanceof ResponseValidationError) {
console.log('ResponseValidationError')
}
if (error.name === 'ResponseValidationError') {
console.log('name is ResponseValidationError')
}
if (error instanceof Error) {
console.log('Error')
}
console.log('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
reply.status(500).send({
statusCode: 500,
error: 'Failed successfully',
})
})
}
I'll add a typeguard for these cases
@kibertoad am I missing something fundamental with how instanceof
works with classes? It looks like it's creating an instance of the class I linked so I'd expect error instanceof ResponseValidationError
to be true. I'm starting to doubt I understand what's going on!
@nickramsbottom instanceof is tricky in JavaScript, it is dependent on classes being from the same realm, see https://stackoverflow.com/questions/68564010/is-it-possible-several-javascript-realms-share-one-single-global-object
If you import a library A, and another library B imports a library A, and you use a class instantiated by library B using class from library A, there is a high chance they will be of a different realm, and won't pass instanceof check. for this reason I highly advise never to rely on instanceof for classes coming from external libraries, but use custom typeguards instead.
@kibertoad Interesting! That's my something new learnt today, thank you