{"id":17646,"library":"express-zod-safe","title":"Express Zod Safe Validation Middleware","description":"Express Zod Safe is a TypeScript-first middleware for Express.js applications, offering robust and typesafe validation of incoming HTTP request bodies, URL parameters, and query strings. It leverages Zod schemas to define validation rules, ensuring data integrity and preventing invalid or malicious data from reaching application logic. The current stable version is 3.2.1, which targets Zod v4.0.0 and above. While a specific release cadence isn't published, it appears to follow Zod's major version updates. Key differentiators include its strict type safety, seamless integration with the Express middleware stack, comprehensive coverage of request parts (body, params, query), and developer-friendly error handling, aiming to be a more robust alternative to similar packages like `zod-express-middleware`.","status":"active","version":"3.2.1","language":"javascript","source_language":"en","source_url":"https://github.com/AngaBlue/express-zod-safe","tags":["javascript","zod","express","middleware","validation","guard","typesafe","typescript"],"install":[{"cmd":"npm install express-zod-safe","lang":"bash","label":"npm"},{"cmd":"yarn add express-zod-safe","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-zod-safe","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"Core web framework integration, peer dependency.","package":"express","optional":false},{"reason":"TypeScript typings for Express, peer dependency.","package":"@types/express","optional":false},{"reason":"Schema definition and validation library, peer dependency.","package":"zod","optional":false}],"imports":[{"note":"`validate` is a default export, not a named one. Importing it with curly braces will result in an undefined value.","wrong":"import { validate } from 'express-zod-safe';","symbol":"validate","correct":"import validate from 'express-zod-safe';"},{"note":"`ValidatedRequest` is a TypeScript type helper. Using `import type` ensures it's stripped from the compiled JavaScript output.","wrong":"import { ValidatedRequest } from 'express-zod-safe';","symbol":"ValidatedRequest","correct":"import type { ValidatedRequest } from 'express-zod-safe';"},{"note":"`z` is the primary named export from the `zod` library, essential for defining schemas. It is not exported by `express-zod-safe` itself.","wrong":"import z from 'zod';","symbol":"z","correct":"import { z } from 'zod';"}],"quickstart":{"code":"import express from 'express';\nimport validate from 'express-zod-safe';\nimport { z } from 'zod';\n\nconst app = express();\napp.use(express.json()); // Essential for parsing JSON bodies\n\n// Define your Zod schemas for request parts\nconst userParamsSchema = z.object({\n  userId: z.string().uuid(),\n});\nconst userQuerySchema = z.object({\n  age: z.coerce.number().optional().default(18), // Coerce string to number, provide default\n  country: z.string().min(2).max(2).optional()\n});\nconst userBodySchema = z.object({\n  name: z.string().min(1, 'Name is required'),\n  email: z.string().email('Invalid email address'),\n  isActive: z.boolean().default(true)\n});\n\n// Use the validate middleware in your route definition\napp.post('/user/:userId', validate({\n  params: userParamsSchema,\n  query: userQuerySchema,\n  body: userBodySchema\n}), (req, res) => {\n  // Access validated data directly from req.body, req.params, req.query\n  console.log('Validated user ID:', req.params.userId);\n  console.log('Validated age:', req.query.age);\n  console.log('Validated body:', req.body);\n  res.status(200).json({ message: 'User data is valid!', data: { userId: req.params.userId, age: req.query.age, ...req.body } });\n});\n\n// Basic error handling middleware for Zod errors\napp.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => {\n  if (err instanceof z.ZodError) {\n    return res.status(400).json({ errors: err.issues });\n  }\n  console.error(err);\n  res.status(500).send('Something broke!');\n});\n\nconst PORT = process.env.PORT || 3000;\napp.listen(PORT, () => console.log(`Server running on port ${PORT}`));\n","lang":"typescript","description":"This quickstart demonstrates how to set up an Express route with `express-zod-safe` to validate URL parameters, query strings, and the request body using Zod schemas, including basic error handling."},"warnings":[{"fix":"Ensure your installed `express-zod-safe` package matches the major version of your `zod` package. Upgrade `zod` to `^4.0.0` for `express-zod-safe@3.x.x` or downgrade `express-zod-safe` to `1.5.4` for `zod@3.x.x`.","message":"Express Zod Safe versions are tied to Zod major versions. For `express-zod-safe@3.x.x`, Zod v4.0.0 or higher is required. Older versions like `express-zod-safe@1.5.4` are compatible with Zod v3.x.x. Using incompatible versions will lead to runtime errors or incorrect validation behavior.","severity":"breaking","affected_versions":">=3.0.0"},{"fix":"Always ensure `app.use(express.json());` (or similar body parsing middleware) is called *before* any route or middleware that uses `express-zod-safe`'s `validate` function.","message":"The `validate` middleware *must* be placed after any other middleware that parses or modifies the request body, such as `express.json()` or `express.urlencoded()`. If `validate` is used before a body parser, `req.body` will be undefined, and body validation will fail or report an empty object.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"For query and path parameters that are expected to be numbers, booleans, or dates, use `z.coerce.number()`, `z.coerce.boolean()`, `z.coerce.date()`, etc., in your Zod schemas.","message":"All query parameters and URL parameters are strings by default in Express. When using Zod schemas for these, use `z.coerce.<type>()` (e.g., `z.coerce.number()`, `z.coerce.boolean()`) if you expect non-string types. Failing to coerce will result in validation errors for non-string input that looks like numbers or booleans.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-23T00:00:00.000Z","next_check":"2026-07-22T00:00:00.000Z","problems":[{"fix":"Ensure all properties (`params`, `query`, `body`) passed to `validate` are defined Zod schemas or empty objects (`z.object({})`) if not needed, instead of being `undefined`.","cause":"Attempting to use `validate({ params, query, body })` without providing one of the schema objects (e.g., `params` was not defined or passed as `undefined`).","error":"TypeError: Cannot destructure property 'params' of 'undefined' as it is undefined."},{"fix":"Add `app.use(express.json());` (or `express.urlencoded()`) early in your middleware chain, ensuring it runs *before* any route handlers or middleware that use `express-zod-safe`.","cause":"This typically occurs when `express.json()` or another body-parsing middleware is missing or placed after the `validate` middleware, leading to an undefined `req.body`.","error":"ZodError: [ { code: 'invalid_type', expected: 'object', received: 'undefined', path: [], message: 'Expected object, received undefined' } ]"},{"fix":"Use the `ValidatedRequest` type from `express-zod-safe` to correctly type your Express `Request` object. For example: `app.post('/user', validate({ body: userSchema }), (req: ValidatedRequest<typeof userSchema>, res) => { ... });`","cause":"TypeScript error when trying to infer types for `req.body`, `req.params`, or `req.query` in a route handler without using the `ValidatedRequest` utility or correctly typing the handler.","error":"Argument of type 'Request<Params, ResBody, ReqBody, ReqQuery>' is not assignable to parameter of type 'object'."}],"ecosystem":"npm","meta_description":null,"install_score":null,"install_tag":null,"quickstart_score":null,"quickstart_tag":null}