Handling @fastify/type-provider-typebox schema validation errors on the frontend
satnamDev-Ops opened this issue · 3 comments
Description:
I am currently using @fastify/type-provider-typebox for schema validation in a Fastify application, and I'm interested in understanding how to handle the validation errors more effectively.
Below is a simplified version of my setup:
app.ts:
export async function build(opts: FastifyOptions): Promise<FastifyInstance> {
const app = fastify(opts)
.setValidatorCompiler(TypeBoxValidatorCompiler)
.withTypeProvider<TypeBoxTypeProvider>();
// Registering routes
app.register(user, { prefix: '/user' });
return app;
}
user.schema.ts:
import { Type, Static } from '@fastify/type-provider-typebox';
export const UserSchema = Type.Object({
firstName: Type.String(),
lastName: Type.String(),
DoB: Type.String(),
});
export type User = Static<typeof UserSchema>;
userRoute.ts:
app.post('/user', { schema: { body: UserSchema } },
async (req: FastifyRequest<{Body: User}>, reply: FastifyReply) => {
return { ...req.body };
}
);
When there's a validation error, the error message I receive is in string format:
{
"statusCode": 400,
"code": "FST_ERR_VALIDATION",
"error": "Bad Request",
"message": "body/lastName Required property, body/DoB Required property, body/lastName Expected string, body/DoB Expected string"
}
I'm concerned about handling these error messages on the frontend as the message is in string format.
To improve this, I tried customizing the error format using the setErrorHandler
method:
app.ts (with custom error format):
export async function build(opts: FastifyOptions): Promise<FastifyInstance> {
const customErrorFormat = (
error: FastifyError,
request: FastifyRequest,
reply: FastifyReply
) => {
if(error.validation){
const structuredErrors: {
keyword: string;
schemaErrors: FastifySchemaValidationError[];
message: string;
}[] = [
{
keyword: 'validation',
schemaErrors: error.validation,
message: error.message,
},
];
return structuredErrors;
}
return error
}
const app = fastify(opts)
.setValidatorCompiler(TypeBoxValidatorCompiler)
.setErrorHandler(customErrorFormat)
.withTypeProvider<TypeBoxTypeProvider>();
// Registering routes
app.register(user, { prefix: '/user' });
return app;
}
With this setup, I get the errors in the following format:
[
{
"keyword": "validation",
"schemaErrors": [
{
"message": "Required property",
"instancePath": "/lastName"
},
{
"message": "Required property",
"instancePath": "/DoB"
},
{
"message": "Expected string",
"instancePath": "/lastName"
},
{
"message": "Expected string",
"instancePath": "/DoB"
}
],
"message": "body/lastName Required property, body/DoB Required property, body/lastName Expected string, body/DoB Expected string"
}
]
While this format is more structured, I'm still unsure if it's the right approach, and I have a few questions:
Questions:
- Is structuring the error message (using
setErrorHandler(customErrorFormat)
) in the provided format the recommended approach for handling schema validation errors? - Can I customize the error messages for each instance path in the schema validation error?
- How do developers typically handle these issues in real-life scenarios when using schema validation?
I would appreciate any insights or advice.
- yes
- yes, by customizing Ajv
- in most modern web apps, form validation does not happen on the server. It's implemented in the client before the data is sent. It allows for a better DX.
@mcollina Thank you!
yes, by customizing Ajv
Is it possible to customize errors in @fastify/type-provider-typebox? I would appreciate a small example if available.