Skip to content

[Bug] Unexpected Continue Pipe since Zod v4 when using ctx.addIssue #4910

@qoomon

Description

@qoomon

Sice v4 ctx.addIssue does continue by default.

In version 3 following transformer does not continue the pipe. In version 4 it does.

If I replace ctx.addIssue with ctx.issues.push it works as expected, see below examples

Zod v4 with ctx.addIssue - Unexpected behavior: does continue pipe

import {z} from 'zod';

export const JsonTransformer = z.string().transform((val, ctx) => {
  try {
    return JSON.parse(val);
  } catch (error: unknown) {
    ctx.addIssue({
      code: 'custom',
      message: (error as { message?: string }).message,
    });
    return z.NEVER;
  }
});


const result = await JsonTransformer.pipe(z.object({
  foo: z.string(),
})).safeParseAsync("invalid");
console.log("error:", result.error?.issues)

Output

 [
  {
    code: 'custom',
    message: `Unexpected token 'i', "invalid" is not valid JSON`,
    path: []
  },
  {
    expected: 'string',
    code: 'invalid_type',
    path: [ 'foo' ],
    message: 'Invalid input: expected string, received undefined'
  }
]

Zod v4 with ctx.addIssue - Works as expected

import {z} from 'zod';

export const JsonTransformer = z.string().transform((val, ctx) => {
  try {
    return JSON.parse(val);
  } catch (error: unknown) {
     ctx.issues.push({
      code: 'custom',
      message: (error as { message?: string }).message,
      input: val,
    });
    return z.NEVER;
  }
});


const result = await JsonTransformer.pipe(z.object({
  foo: z.string(),
})).safeParseAsync("invalid");
console.log("error:", result.error?.issues)

Output

 [
  {
    code: 'custom',
    message: `Unexpected token 'i', "invalid" is not valid JSON`,
    path: []
  }
]

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