> ## Documentation Index
> Fetch the complete documentation index at: https://docs.codemod.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Zod 3 to 4 Migration

Zod 4 introduces a cleaner API, improved TypeScript inference, and several breaking changes aimed at making schema validation both stricter *and* more ergonomic.

Key highlights include:

1. **Unified Object Behaviour** – `.passthrough()` replaces `.nonstrict()` and better aligns with Zod’s philosophy of explicitness.
2. **Enhanced Metadata APIs** – `meta()` supersedes several ad-hoc helpers such as `.describe()`.
3. **Error Handling Revamp** – new `ZodError` export path and richer error objects.
4. **Union & Intersection Updates** – explicit helpers (`z.union`, `z.intersection`) over chained `.or()` / `.and()` calls.
5. **Ecosystem Clean-up** – deprecated utilities removed, smaller bundle size, faster parse times.

For a full changelog see the [Zod v4 release notes](https://github.com/colinhacks/zod/releases/tag/v4.0.1).

Codemod provides an automated Zod 3 → 4 upgrade experience. This page walks you through running the codemod and polishing the remaining edge-cases.

## Getting started

<CardGroup cols={2}>
  <Card title="Zod 4 Release Notes" icon="book-open" href="https://github.com/colinhacks/zod/releases/tag/v4.0.1" />

  <Card title="Zod 4 Migration Recipe" icon="cauldron" href="https://app.codemod.com/registry/zod-3-4" />
</CardGroup>

## Migration Steps

<Steps>
  <Step title="Install Zod 4">
    Install the latest major version of Zod. We recommend using **exact** versions to avoid surprises:

    ```bash theme={null}
    npm install --save-exact zod@^4
    # or
    yarn add --exact zod@^4
    ```

    Zod has no peer dependencies, so that’s the only package you need to bump.
  </Step>

  <Step title="Run the codemod">
    Launch the codemod recipe to automatically rewrite common breaking changes:

    ```bash theme={null}
    npx codemod jssg run zod-3-4
    ```

    <Tip>
      **Can you rollback?**

      Git is your friend—commit before you run the codemod. The Codemod CLI also supports the [`--dry-run` flag](https://docs.codemod.com/cli#param-dry-run) which lets you preview the changes without applying them.
    </Tip>

    View a list of available CLI commands & options [here ->](https://docs.codemod.com/cli)

    #### What the recipe changes

    The migration recipe **only** targets Zod-specific breaking changes. It will *not* touch unrelated code patterns like `var` declarations or debug `console.log` statements. Concretely, it performs the following refactors:

    * `.nonstrict()` → `.passthrough()`
    * Chained `.or()` / `.and()` calls → `z.union([...])` / `z.intersection([...])`
    * `.describe("…")` → `.meta({ description: "…" })`
    * Updates `ZodError`, `z.ZodSchema` import paths to the new `zod/v4` entrypoints
    * Removes helpers removed in v4 (`z.lazyobject`, legacy refinements, etc.)

    If you see documentation elsewhere mentioning generic tasks such as *“modernizing syntax patterns”* or *“removing debug statements”*, those refer to different codemods—not this Zod migration.
  </Step>

  <Step title="Review & test">
    The codemod handles *most* changes, but some APIs require manual tweaks. We recommend:

    1. **Type-check** the project:
       ```bash theme={null}
       pnpm tsc --noEmit
       ```
    2. **Run your test suite** and fix any remaining failures.
    3. Search for `TODO(zod-4-migration)` comments the codemod leaves behind for ambiguous cases.
  </Step>

  <Step title="Before & After examples">
    Below is a non-exhaustive diff generated by the codemod:

    ```tsx diff theme={null}
    -import { z, ZodError } from "zod";
    +import { z } from "zod/v4";
    +import { ZodError } from "zod/v4/core";

    -const value = z.literal('yes').or(z.literal('no'));
    +const value = z.union([
    +  z.literal('yes'),
    +  z.literal('no'),
    +]);

    -const password = z.string().min(8).describe("User's password");
    +const password = z.string().min(8).meta({ description: "User's password" });
    ```
  </Step>
</Steps>

## Tested versions

| From         | To          | Languages               |
| ------------ | ----------- | ----------------------- |
| `zod@3.22.x` | `zod@4.0.0` | JavaScript & TypeScript |

## FAQ

### Does the codemod cover *every* breaking change?

No. It focuses on the highest-impact, mechanical updates. Review the Zod release notes for edge-cases such as custom `.refine()` logic or plugin APIs.

### My project uses Babel / SWC – is that supported?

Yes. The codemod operates on the output AST and is agnostic of the underlying compiler.
