Skip to content

Zod v4: transform() runs even when .refine() fails, causing unexpected runtime errors #4926

@AntoniusGolly

Description

@AntoniusGolly

In Zod v4, when chaining .refine() and .transform() on a schema, the .transform() function is still executed even if .refine() fails. This can lead to unexpected runtime exceptions (e.g. SyntaxError) during .parse() or .safeParse().

This behavior is surprising and different from v3 where transformation is expected to run only if validation succeeds.

The migration guide has no mentioning of it. Disclaimer, maybe I'm misusing the schema and can fix on my side.

Example

import { z } from 'zod'

const Schema = z.string()
  .refine((val) => {
    try {
      JSON.parse(val)
      return true
    } catch {
      return false
    }
  }, { message: 'must be valid JSON stringified array' })
  .transform((val) => JSON.parse(val)) // <-- this runs even if refine fails

// Invalid input: not JSON
const result = Schema.safeParse('this-is-not-json')
console.log(result)

Instead of returning { success: false, error: ZodError }, it throws:

Uncaught SyntaxError: Unexpected token h in JSON at position 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions