On this Page
On this Guide
- Lesson 13: Validating a User Registration Form
- Lesson 14: Validating API Query Parameters
- Lesson 15: Validating Environment Variables
- Lesson 16: Handling Nested Errors and Formatted Output
- Lesson 17: Reusable Zod Error Parser for Forms
- Lesson 18: Blog Post Editor β Real-World Case Study
- Lesson 19: Zod + React Hook Form Integration
- Lesson 21: Validating Express Requests with Zod
- Lesson 22: Custom Zod Error Formatter for Express APIs
- Lesson 20: Final Thoughts, Best Practices, and Resources
The Problem
When validating complex objects like:
const schema = z.object({
user: z.object({
name: z.string().min(2),
email: z.string().email(),
}),
});
You want to surface meaningful error messages for nested fields like:
user.nameuser.email
But raw Zod errors can be verbose. Letβs fix that.
Nested Validation Errors
const result = schema.safeParse({
user: {
name: "",
email: "not-an-email",
},
});
If validation fails, the result is:
{
success: false,
error: ZodError
}
Using error.format()
Zod provides a great method to structure errors by field:
if (!result.success) {
console.log(result.error.format());
}
This returns a tree-like object:
{
user: {
name: { _errors: ["String must contain at least 2 characters"] },
email: { _errors: ["Invalid email"] }
},
_errors: []
}
Perfect for building inline form error messages.
Flattening Errors for Form Inputs
You can also flatten all errors into a simpler format:
const flat = result.error.flatten();
console.log(flat.fieldErrors);
// β {
// "user.name": undefined,
// "user.email": ["Invalid email"]
// }
> Note: flatten() works best on flat schemas. For deeply nested ones, use .format() instead.
Custom Error Paths
If you’re using .superRefine() or .addIssue(), you can control which field gets the error:
ctx.addIssue({
path: ["user", "email"],
code: z.ZodIssueCode.custom,
message: "This email already exists",
});
This ensures the error appears exactly where you want it.
Summary
- Use
.format()to get a structured object of errors per field - Use
.flatten()to get a simple key-value structure - Use
pathin.addIssue()for accurate error targeting - Zod makes it easy to wire backend errors into frontend UIs
Next: Lesson 17 β Creating a Reusable Zod Error Parser for Forms
Master the Code, Be the Guru!