Skip to content

keyValidator._parse crash: @workflow/world-local mixes zod v3 compat and zod/v4 native schemas #1587

@dlhck

Description

@dlhck

Bug

@workflow/world-local/dist/queue.js imports zod (v3 compat) and creates a z.object() containing schemas from @workflow/world/dist/queue.js, which imports from zod/v4 (native). When Zod v3's ZodObject._parse() iterates the shape, it calls ._parse() on the v4-native schemas — which don't have that method.

TypeError: keyValidator._parse is not a function

Root cause

@workflow/world/dist/queue.js (line 1):

import { z } from 'zod/v4';  // native v4

Creates ValidQueueName, MessageId etc. as v4-native schemas.

@workflow/world-local/dist/queue.js (line 7):

import z from 'zod';  // v3 compat layer

Then mixes them:

const HeaderParser = z.object({
    'x-vqs-queue-name': ValidQueueName,  // v4 native — no ._parse()
    'x-vqs-message-id': MessageId,        // v4 native — no ._parse()
    'x-vqs-message-attempt': z.coerce.number(), // v3 compat
});

When HeaderParser.safeParse() runs, v3's internal ZodObject._parse() calls shape[key]._parse() on each value. The v4-native schemas don't have ._parse() → crash.

Reproduction

  1. Use zod@^3.25 (v4 published under v3 semver, with v3 compat layer)
  2. Use workflow@4.2.0-beta.75
  3. Trigger any workflow → POST /.well-known/workflow/v1/flow returns 500

Affected versions

  • @workflow/world@4.1.0-beta.15
  • @workflow/world-local@4.1.0-beta.48
  • Also present in older versions (4.0.1-beta.x)

Workaround

Patch @workflow/world-local/dist/queue.js to use import { z } from 'zod/v4' instead of import z from 'zod'.

Suggested fix

Either consistently use zod/v4 in both packages, or consistently use zod (v3 compat). Since @workflow/world/dist/queue.js uses z.templateLiteral() (v4-only API), the fix should be to change @workflow/world-local to also import from zod/v4.

Related

This is the same crash as #686 but with the actual root cause identified. That issue was closed with "upgrade to Zod 4" which only masks the bug.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions