hono
hono copied to clipboard
Feature Req: Use zod-validation-error to parse zod errors
There is an excellent library that makes the responses from Zod validation errors much more useful and human friendly.
I would suggest incorporating this into the Zod validation middleware.
https://github.com/causaly/zod-validation-error/
They recommend this lib in the Zod docs.
https://zod.dev/?id=error-handling
zValidator
middleware currently has an optional hook
argument that allows you to add logic before the middleware sends its 400
response, and optionally override the response completely (source)
import { fromZodError } from 'zod-validation-error';
// You could use this to log a human-formatted error
app.post(
'/post',
zValidator('json', schema, (result, c) => {
if (!result.success) {
console.error(fromZodError(result.error))
}
})
)
// Or send the formatted error as part of the response
app.post(
'/post',
zValidator('json', schema, (result, c) => {
if (!result.success) {
const validationError = fromZodError(result.error)
return c.json({ error: validationError.message }, 400)
}
})
)
Thanks @christophemarois. I've been handling it in the top level onError() handler to format the response. I'll take a look at this more granular approach too.
These instructions might make a nice addition to the middleware docs since parsing Zod errors is not as trivial as it should be.
You can always bring your own zValidator (BYOZV) 😉
import type { ValidationTargets } from 'hono';
import { validator } from 'hono/validator';
import type { ZodSchema, z } from 'zod';
import { handlePayloadValidationError } from '@/error';
export const zValidator = <T extends ZodSchema, Target extends keyof ValidationTargets>(
target: Target,
schema: T
) =>
validator(target, async (value, c) => {
const result = await schema.parseAsync(value).catch(handlePayloadValidationError);
const data = result.data as z.infer<T>;
return data;
});