codez.guru

Why Format Zod Errors?

By default, Zod gives you a rich error object. But clients often expect:

  • A clean structure
  • Flat key-value errors
  • Easy-to-display messages in forms or frontend UIs

Instead of returning raw .issues, let’s format errors into something like:

{
  "errors": {
    "email": "Invalid email",
    "password": "Too short"
  }
}

What a Good API Error Response Looks Like

Here’s a simple, predictable structure:

{
  "status": "error",
  "message": "Validation failed",
  "errors": {
    "field": "Error message"
  }
}

Let’s build a utility to do that.


Creating a Zod Error Formatter

import { ZodError } from "zod";

export function formatZodError(error: ZodError) {
  const formatted: Record<string string> = {};

  for (const issue of error.issues) {
    const path = issue.path.join(".");
    if (!formatted[path]) {
      formatted[path] = issue.message;
    }
  }

  return {
    status: "error",
    message: "Validation failed",
    errors: formatted,
  };
}

This gives you a clean, flat object ready to send to any client.


Using It in Middleware

Update your validation middleware to use it:

import { formatZodError } from "@/utils/formatZodError";

export const validate =
  <t>(schema: ZodSchema<t>) =&gt;
  (req: Request, res: Response, next: NextFunction) =&gt; {
    const result = schema.safeParse(req.body);
    if (!result.success) {
      return res.status(400).json(formatZodError(result.error));
    }
    req.body = result.data;
    next();
  };

Optional: Global Express Error Handler

For apps with multiple validation points or thrown errors:

app.use((err, req, res, next) =&gt; {
  if (err instanceof ZodError) {
    return res.status(400).json(formatZodError(err));
  }

  console.error(err);
  res.status(500).json({ status: "error", message: "Internal Server Error" });
});

Summary

  • Use a consistent structure for API validation errors
  • Build a reusable formatZodError() utility
  • Integrate it into middleware or global error handlers
  • Clients love predictable error formats β€” your future self will too

Master the Code, Be the Guru!