Zod v3 to v4 Codemod
This codemod automatically migrates your Zod schemas and validation logic from Zod v3 to Zod v4, based on the official Zod v4 Changelog and API Reference.
✅ What it does
This codemod transforms deprecated or changed APIs to their v4 equivalents. It focuses on making your codebase compliant with Zod v4's improved and unified error handling, updated object and string APIs, and other key breaking changes.
🔧 Transforms Included
1. message
→ error
Before:
z.string().min(5, { message: 'Too short.' });
After:
z.string().min(5, { error: 'Too short.' });
2. required_error
/ invalid_type_error
→ error
function
Before:
z.string({ required_error: 'This field is required', invalid_type_error: 'Not a string', });
After:
z.string({ error: (issue) => issue.input === undefined ? 'This field is required' : 'Not a string' });
3. errorMap
→ error
Before:
z.string({ errorMap: (issue, ctx) => { if (issue.code === 'too_small') { return { message: `Value must be >${issue.minimum}` }; } return { message: ctx.defaultError }; }, });
After:
z.string({ error: (issue) => { if (issue.code === 'too_small') { return `Value must be >${issue.minimum}`; } } });
4. .strict()
, .passthrough()
, .strip()
Before:
z.object({ name: z.string() }).strict(); z.object({ name: z.string() }).passthrough(); z.object({ name: z.string() }).strip();
After:
z.strictObject({ name: z.string() }); z.looseObject({ name: z.string() }); z.object({ name: z.string() }); // strip is now default
5. Deprecated z.string().email()
and similar → Top-level APIs
Before:
z.string().email(); z.string().uuid(); z.string().url();
After:
z.email(); z.uuid(); z.url();
6. z.record(schema)
→ z.record(keySchema, valueSchema)
Before:
z.record(z.string());
After:
z.record(z.string(), z.string());
⚠️ This transformation assumes both key and value are strings. Customize as needed.
7. ZodError instanceof Error
ZodError no longer extends Error
, so instanceof
checks against Error
may no longer work.
Before:
if (err instanceof z.ZodError || err instanceof Error) {}
After:
if (err instanceof z.ZodError) {}
💡 Other Considerations
While this codemod automates a large portion of the migration, you may still need to:
- Manually inspect rare Zod APIs like
.function()
,.promise()
, or.literal(Symbol)
- Adjust error-handling logic or custom utilities that rely on
ZodError
internals
Refer to the full official changelog for advanced topics: