Skip to content

[world-local,world-vercel,world-postgres] Fix zod v3/v4 schema mismatch crash#1588

Merged
VaguelySerious merged 1 commit intomainfrom
peter/issue-1587
Apr 2, 2026
Merged

[world-local,world-vercel,world-postgres] Fix zod v3/v4 schema mismatch crash#1588
VaguelySerious merged 1 commit intomainfrom
peter/issue-1587

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

Closes #1587

Summary

  • @workflow/world/queue.ts exports schemas created with zod/v4 (native). When world-local, world-vercel, and world-postgres import these schemas and embed them inside z.object() calls using zod (v3 compat layer), the v3 internal ._parse() method is called on v4-native schemas which lack it, causing TypeError: keyValidator._parse is not a function.
  • Fix: change all queue-related files that import v4-native schemas from @workflow/world to also use import { z } from 'zod/v4'.
  • Added regression test in world-local that validates the schema compatibility.

Test plan

  • Reproduced externally with published workflow@4.2.0-beta.75 + zod@^3.25
  • All 263 world-local tests pass (262 existing + 1 new regression test)
  • Full typecheck passes across all packages
  • Build succeeds for all 28 packages
  • CI checks pass

🤖 Generated with Claude Code

…es to match @workflow/world schemas

@workflow/world/queue.ts exports schemas created with zod/v4 (native).
When consumers (world-local, world-vercel, world-postgres) import these
schemas and embed them in z.object() calls using zod v3 compat, the v3
internal _parse() method is called on v4-native schemas which don't have
it, causing "keyValidator._parse is not a function".

Fix by changing all queue-related files that import v4-native schemas
from @workflow/world to also use zod/v4.

Closes #1587

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 2, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
example-nextjs-workflow-turbopack Ready Ready Preview, Comment Apr 2, 2026 4:17pm
example-nextjs-workflow-webpack Ready Ready Preview, Comment Apr 2, 2026 4:17pm
example-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-astro-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-express-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-fastify-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-hono-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-nitro-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-nuxt-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-sveltekit-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workbench-vite-workflow Ready Ready Preview, Comment Apr 2, 2026 4:17pm
workflow-docs Ready Ready Preview, Comment, Open in v0 Apr 2, 2026 4:17pm
workflow-swc-playground Ready Ready Preview, Comment Apr 2, 2026 4:17pm

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented Apr 2, 2026

🦋 Changeset detected

Latest commit: 52fe35a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 19 packages
Name Type
@workflow/world-local Patch
@workflow/world-vercel Patch
@workflow/world-postgres Patch
@workflow/cli Patch
@workflow/core Patch
@workflow/vitest Patch
workflow Patch
@workflow/world-testing Patch
@workflow/builders Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/web-shared Patch
@workflow/ai Patch
@workflow/astro Patch
@workflow/nest Patch
@workflow/rollup Patch
@workflow/sveltekit Patch
@workflow/vite Patch
@workflow/nuxt Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 2, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
✅ ▲ Vercel Production 857 0 67 924
✅ 💻 Local Development 830 0 178 1008
✅ 📦 Local Production 830 0 178 1008
✅ 🐘 Local Postgres 830 0 178 1008
✅ 🪟 Windows 76 0 8 84
❌ 🌍 Community Worlds 133 59 24 216
✅ 📋 Other 210 0 42 252
Total 3766 59 675 4500

❌ Failed Tests

🌍 Community Worlds (59 failed)

mongodb (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN7FSNPND3WNJ27G1XD3PB07
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN7G1SVFZ3T823KD37CPPXXB

redis (2 failed):

  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN7FSNPND3WNJ27G1XD3PB07
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN7G1SVFZ3T823KD37CPPXXB

turso (55 failed):

  • addTenWorkflow | wrun_01KN7FRETDTR56X2EVAKV5WBR0
  • addTenWorkflow | wrun_01KN7FRETDTR56X2EVAKV5WBR0
  • wellKnownAgentWorkflow (.well-known/agent) | wrun_01KN7FSNS14GTS0VDCDKM8G1XQ
  • should work with react rendering in step
  • promiseAllWorkflow | wrun_01KN7FRNSF91CRRHY13J3TYZQN
  • promiseRaceWorkflow | wrun_01KN7FRTC4DM1RZSGX7NEAZMM5
  • promiseAnyWorkflow | wrun_01KN7FRWM5R8X73PH2HTAB6XPQ
  • importedStepOnlyWorkflow | wrun_01KN7FT169F1NZ8ZHS4VR96G03
  • hookWorkflow | wrun_01KN7FS8T38AEF25Y1G6RT3J2P
  • hookWorkflow is not resumable via public webhook endpoint | wrun_01KN7FSNPND3WNJ27G1XD3PB07
  • webhookWorkflow | wrun_01KN7FSYJH4FNGFRS2NFX24B2N
  • sleepingWorkflow | wrun_01KN7FT5A9MADC6MMDYQV9K8GR
  • parallelSleepWorkflow | wrun_01KN7FTJ5SDD222V1ATVV1C1ND
  • nullByteWorkflow | wrun_01KN7FTPXRV6A0WJ384S6KGB6S
  • workflowAndStepMetadataWorkflow | wrun_01KN7FTS825ARSD9MTHBDRE1VD
  • fetchWorkflow | wrun_01KN7FXG2X10CA84QRSFBTX0G2
  • promiseRaceStressTestWorkflow | wrun_01KN7FXKQ6P34RN4C0D71EW0B6
  • error handling error propagation workflow errors nested function calls preserve message and stack trace
  • error handling error propagation workflow errors cross-file imports preserve message and stack trace
  • error handling error propagation step errors basic step error preserves message and stack trace
  • error handling error propagation step errors cross-file step error preserves message and function names in stack
  • error handling retry behavior regular Error retries until success
  • error handling retry behavior FatalError fails immediately without retries
  • error handling retry behavior RetryableError respects custom retryAfter delay
  • error handling retry behavior maxRetries=0 disables retries
  • error handling catchability FatalError can be caught and detected with FatalError.is()
  • error handling not registered WorkflowNotRegisteredError fails the run when workflow does not exist
  • error handling not registered StepNotRegisteredError fails the step but workflow can catch it
  • error handling not registered StepNotRegisteredError fails the run when not caught in workflow
  • hookCleanupTestWorkflow - hook token reuse after workflow completion | wrun_01KN7G14GT172PA81SKD26KJ2R
  • concurrent hook token conflict - two workflows cannot use the same hook token simultaneously | wrun_01KN7G1SVFZ3T823KD37CPPXXB
  • hookDisposeTestWorkflow - hook token reuse after explicit disposal while workflow still running | wrun_01KN7G2FPTSYKZJZQ81KVXX7P3
  • stepFunctionPassingWorkflow - step function references can be passed as arguments (without closure vars) | wrun_01KN7G34PBQX1BFJ9PKZRR3TK9
  • stepFunctionWithClosureWorkflow - step function with closure variables passed as argument | wrun_01KN7G3DZFMG8HYJHTQ649XRSW
  • closureVariableWorkflow - nested step functions with closure variables | wrun_01KN7G3KP6X560D7EEFXB3Y8RT
  • spawnWorkflowFromStepWorkflow - spawning a child workflow using start() inside a step | wrun_01KN7G3P0CZ1ARS01F18TQ9WNK
  • health check (queue-based) - workflow and step endpoints respond to health check messages
  • pathsAliasWorkflow - TypeScript path aliases resolve correctly | wrun_01KN7G45T3RTPJ17PM79KFAWZF
  • Calculator.calculate - static workflow method using static step methods from another class | wrun_01KN7G4BNXASERW7Q48TYWREX1
  • AllInOneService.processNumber - static workflow method using sibling static step methods | wrun_01KN7G4JT0M3NS3ASBV2AHHPM2
  • ChainableService.processWithThis - static step methods using this to reference the class | wrun_01KN7G4RKE5F8DV6AKC8YYY2X7
  • thisSerializationWorkflow - step function invoked with .call() and .apply() | wrun_01KN7G4ZFQT2YGMMK7TH246EFH
  • customSerializationWorkflow - custom class serialization with WORKFLOW_SERIALIZE/WORKFLOW_DESERIALIZE | wrun_01KN7G56MF1JXGW1RA3PWWZF5K
  • instanceMethodStepWorkflow - instance methods with "use step" directive | wrun_01KN7G5ESBZN3BW7F66PSB50C8
  • crossContextSerdeWorkflow - classes defined in step code are deserializable in workflow context | wrun_01KN7G5T5A6X1HC78WFB0BME14
  • stepFunctionAsStartArgWorkflow - step function reference passed as start() argument | wrun_01KN7G63JDMC01PQNX3NQWFQDC
  • cancelRun - cancelling a running workflow | wrun_01KN7G6ACA1WMS6WSH6CKPA5Y4
  • cancelRun via CLI - cancelling a running workflow | wrun_01KN7G6KRFSQ8AHTVBWPBY1C62
  • pages router addTenWorkflow via pages router
  • pages router promiseAllWorkflow via pages router
  • pages router sleepingWorkflow via pages router
  • hookWithSleepWorkflow - hook payloads delivered correctly with concurrent sleep | wrun_01KN7G7074JJPG31CM0W0TNKEK
  • sleepInLoopWorkflow - sleep inside loop with steps actually delays each iteration | wrun_01KN7G7MTPCVAHBGSAV56TRP5G
  • sleepWithSequentialStepsWorkflow - sequential steps work with concurrent sleep (control) | wrun_01KN7G7ZD86AHZY2PSSDJ611Y0
  • importMetaUrlWorkflow - import.meta.url is available in step bundles | wrun_01KN7G8677X6CTCANG4DDEJCFP

Details by Category

✅ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 77 0 7
✅ example 77 0 7
✅ express 77 0 7
✅ fastify 77 0 7
✅ hono 77 0 7
✅ nextjs-turbopack 82 0 2
✅ nextjs-webpack 82 0 2
✅ nitro 77 0 7
✅ nuxt 77 0 7
✅ sveltekit 77 0 7
✅ vite 77 0 7
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 70 0 14
✅ express-stable 70 0 14
✅ fastify-stable 70 0 14
✅ hono-stable 70 0 14
✅ nextjs-turbopack-canary 59 0 25
✅ nextjs-turbopack-stable 76 0 8
✅ nextjs-webpack-canary 59 0 25
✅ nextjs-webpack-stable 76 0 8
✅ nitro-stable 70 0 14
✅ nuxt-stable 70 0 14
✅ sveltekit-stable 70 0 14
✅ vite-stable 70 0 14
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 76 0 8
❌ 🌍 Community Worlds
App Passed Failed Skipped
✅ mongodb-dev 5 0 0
❌ mongodb 57 2 8
✅ redis-dev 5 0 0
❌ redis 57 2 8
✅ turso-dev 5 0 0
❌ turso 4 55 8
✅ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 70 0 14
✅ e2e-local-postgres-nest-stable 70 0 14
✅ e2e-local-prod-nest-stable 70 0 14

📋 View full workflow run

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 2, 2026

📊 Benchmark Results

📈 Comparing against baseline from main branch. Green 🟢 = faster, Red 🔺 = slower.

workflow with no steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Nitro 0.042s (-5.2% 🟢) 1.005s (~) 0.963s 10 1.00x
💻 Local Express 0.044s (-3.3%) 1.006s (~) 0.962s 10 1.04x
💻 Local Next.js (Turbopack) 0.048s (-6.9% 🟢) 1.005s (~) 0.957s 10 1.15x
🌐 Redis Next.js (Turbopack) 0.052s (+17.0% 🔺) 1.005s (~) 0.953s 10 1.23x
🐘 Postgres Nitro 0.060s (-14.2% 🟢) 1.011s (~) 0.951s 10 1.42x
🐘 Postgres Next.js (Turbopack) 0.060s (-10.1% 🟢) 1.012s (~) 0.952s 10 1.43x
🐘 Postgres Express 0.062s (-10.0% 🟢) 1.012s (~) 0.950s 10 1.48x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 0.445s (-11.6% 🟢) 2.325s (-13.7% 🟢) 1.880s 10 1.00x
▲ Vercel Nitro 0.505s (-3.6%) 2.566s (-6.6% 🟢) 2.061s 10 1.14x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 1 step

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 1.121s (~) 2.006s (~) 0.885s 10 1.00x
🌐 Redis Next.js (Turbopack) 1.125s (+1.1%) 2.006s (~) 0.882s 10 1.00x
💻 Local Express 1.128s (~) 2.005s (~) 0.877s 10 1.01x
💻 Local Nitro 1.131s (~) 2.006s (~) 0.874s 10 1.01x
🐘 Postgres Next.js (Turbopack) 1.144s (~) 2.013s (~) 0.869s 10 1.02x
🐘 Postgres Nitro 1.149s (~) 2.011s (~) 0.862s 10 1.02x
🐘 Postgres Express 1.157s (+0.5%) 2.012s (~) 0.855s 10 1.03x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.133s (-5.8% 🟢) 3.572s (-9.7% 🟢) 1.439s 10 1.00x
▲ Vercel Nitro 2.205s (+5.9% 🔺) 3.743s (-4.0%) 1.538s 10 1.03x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 10 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 10.746s (+1.5%) 11.023s (~) 0.277s 3 1.00x
💻 Local Next.js (Turbopack) 10.829s (~) 11.023s (~) 0.194s 3 1.01x
🐘 Postgres Nitro 10.883s (~) 11.023s (~) 0.140s 3 1.01x
🐘 Postgres Express 10.909s (~) 11.030s (~) 0.121s 3 1.02x
🐘 Postgres Next.js (Turbopack) 10.910s (~) 11.025s (~) 0.116s 3 1.02x
💻 Local Nitro 10.920s (~) 11.023s (~) 0.103s 3 1.02x
💻 Local Express 10.937s (~) 11.023s (~) 0.086s 3 1.02x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 17.270s (-1.5%) 19.158s (-2.5%) 1.888s 2 1.00x
▲ Vercel Nitro 17.811s (-22.7% 🟢) 19.473s (-23.4% 🟢) 1.663s 2 1.03x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 25 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 14.278s (+2.8%) 15.029s (+5.6% 🔺) 0.751s 4 1.00x
🐘 Postgres Nitro 14.476s (-0.9%) 15.022s (~) 0.546s 4 1.01x
💻 Local Next.js (Turbopack) 14.589s (~) 15.030s (~) 0.441s 4 1.02x
🐘 Postgres Express 14.638s (~) 15.026s (~) 0.388s 4 1.03x
🐘 Postgres Next.js (Turbopack) 14.649s (+1.2%) 15.023s (~) 0.374s 4 1.03x
💻 Local Nitro 14.946s (~) 15.029s (~) 0.083s 4 1.05x
💻 Local Express 14.990s (~) 15.030s (~) 0.040s 4 1.05x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 30.940s (-3.8%) 32.693s (-4.2%) 1.753s 2 1.00x
▲ Vercel Express 31.776s (-9.2% 🟢) 33.164s (-9.9% 🟢) 1.388s 2 1.03x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 sequential steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 13.418s (+6.4% 🔺) 14.024s (+7.7% 🔺) 0.606s 7 1.00x
🐘 Postgres Nitro 13.858s (-1.7%) 14.022s (-4.9%) 0.164s 7 1.03x
🐘 Postgres Next.js (Turbopack) 14.057s (+0.8%) 14.742s (+4.0%) 0.685s 7 1.05x
🐘 Postgres Express 14.061s (-2.3%) 14.597s (-2.8%) 0.536s 7 1.05x
💻 Local Next.js (Turbopack) 15.921s (-2.1%) 16.197s (-4.9%) 0.276s 6 1.19x
💻 Local Nitro 16.311s (-1.5%) 17.030s (~) 0.719s 6 1.22x
💻 Local Express 16.637s (~) 17.031s (~) 0.394s 6 1.24x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 52.818s (-8.2% 🟢) 54.280s (-9.5% 🟢) 1.462s 2 1.00x
▲ Vercel Express 55.513s (-1.2%) 56.740s (-2.4%) 1.227s 2 1.05x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.all with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.240s (~) 2.010s (~) 0.770s 15 1.00x
🐘 Postgres Nitro 1.260s (~) 2.010s (~) 0.750s 15 1.02x
🐘 Postgres Express 1.267s (-0.6%) 2.011s (~) 0.744s 15 1.02x
🌐 Redis Next.js (Turbopack) 1.291s (+5.5% 🔺) 2.006s (~) 0.715s 15 1.04x
💻 Local Nitro 1.495s (-2.5%) 2.005s (~) 0.510s 15 1.21x
💻 Local Next.js (Turbopack) 1.516s (-3.6%) 2.005s (~) 0.489s 15 1.22x
💻 Local Express 1.517s (-1.5%) 2.005s (~) 0.488s 15 1.22x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.275s (-6.6% 🟢) 3.797s (-5.9% 🟢) 1.522s 8 1.00x
▲ Vercel Express 2.473s (-4.5%) 3.795s (-15.4% 🟢) 1.321s 8 1.09x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Promise.all with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.319s (-1.3%) 3.010s (~) 0.691s 10 1.00x
🐘 Postgres Express 2.334s (-1.4%) 3.010s (~) 0.676s 10 1.01x
🐘 Postgres Next.js (Turbopack) 2.450s (~) 3.013s (~) 0.564s 10 1.06x
🌐 Redis Next.js (Turbopack) 2.505s (+4.1%) 3.008s (~) 0.503s 10 1.08x
💻 Local Next.js (Turbopack) 2.824s (+0.8%) 3.343s (-3.2%) 0.519s 9 1.22x
💻 Local Nitro 2.881s (-2.8%) 3.342s (-3.2%) 0.461s 9 1.24x
💻 Local Express 3.083s (+5.3% 🔺) 3.762s (+25.1% 🔺) 0.680s 8 1.33x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.654s (+1.0%) 3.949s (-9.5% 🟢) 1.295s 9 1.00x
▲ Vercel Nitro 3.225s (+13.3% 🔺) 4.504s (+5.5% 🔺) 1.278s 7 1.22x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.all with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.457s (-0.6%) 4.011s (~) 0.554s 8 1.00x
🐘 Postgres Express 3.479s (~) 4.013s (~) 0.533s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.670s (+0.7%) 4.014s (~) 0.344s 8 1.06x
🌐 Redis Next.js (Turbopack) 4.123s (+5.5% 🔺) 4.868s (+17.7% 🔺) 0.744s 7 1.19x
💻 Local Nitro 7.602s (-5.4% 🟢) 8.020s (-5.9% 🟢) 0.418s 4 2.20x
💻 Local Next.js (Turbopack) 7.618s (-2.6%) 8.018s (-5.9% 🟢) 0.400s 4 2.20x
💻 Local Express 8.224s (+0.8%) 8.773s (-2.8%) 0.549s 4 2.38x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 3.474s (-5.0% 🟢) 5.118s (-9.9% 🟢) 1.644s 6 1.00x
▲ Vercel Nitro 3.542s (+16.6% 🔺) 5.315s (+5.1% 🔺) 1.773s 6 1.02x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 10 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 1.227s (-0.6%) 2.011s (~) 0.784s 15 1.00x
🐘 Postgres Express 1.260s (~) 2.009s (~) 0.749s 15 1.03x
🐘 Postgres Nitro 1.264s (~) 2.008s (~) 0.745s 15 1.03x
🌐 Redis Next.js (Turbopack) 1.297s (+5.3% 🔺) 2.006s (~) 0.709s 15 1.06x
💻 Local Nitro 1.536s (-2.5%) 2.006s (~) 0.470s 15 1.25x
💻 Local Next.js (Turbopack) 1.539s (+2.3%) 2.007s (~) 0.467s 15 1.26x
💻 Local Express 1.544s (-0.8%) 2.005s (~) 0.461s 15 1.26x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.438s (+5.1% 🔺) 3.909s (-2.4%) 1.472s 9 1.00x
▲ Vercel Nitro 2.458s (~) 4.070s (+1.9%) 1.612s 8 1.01x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 25 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 2.307s (-2.1%) 3.011s (~) 0.704s 10 1.00x
🐘 Postgres Express 2.380s (+2.7%) 3.012s (~) 0.632s 10 1.03x
🐘 Postgres Next.js (Turbopack) 2.404s (~) 3.013s (~) 0.609s 10 1.04x
🌐 Redis Next.js (Turbopack) 2.554s (+5.8% 🔺) 3.008s (~) 0.454s 10 1.11x
💻 Local Next.js (Turbopack) 2.772s (-8.6% 🟢) 3.209s (-7.1% 🟢) 0.437s 10 1.20x
💻 Local Nitro 2.891s (-5.2% 🟢) 3.007s (-22.6% 🟢) 0.116s 10 1.25x
💻 Local Express 3.001s (-3.9%) 3.762s (-3.3%) 0.761s 8 1.30x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 2.490s (-14.8% 🟢) 3.806s (-16.2% 🟢) 1.315s 8 1.00x
▲ Vercel Nitro 3.272s (+13.0% 🔺) 4.927s (+14.2% 🔺) 1.655s 7 1.31x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

Promise.race with 50 concurrent steps

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Nitro 3.475s (-0.6%) 4.012s (~) 0.537s 8 1.00x
🐘 Postgres Express 3.494s (~) 4.012s (~) 0.517s 8 1.01x
🐘 Postgres Next.js (Turbopack) 3.679s (~) 4.015s (~) 0.337s 8 1.06x
🌐 Redis Next.js (Turbopack) 4.127s (+5.4% 🔺) 4.869s (+9.7% 🔺) 0.742s 7 1.19x
💻 Local Next.js (Turbopack) 7.919s (-4.0%) 8.770s (+3.0%) 0.851s 4 2.28x
💻 Local Nitro 8.482s (-1.6%) 9.023s (~) 0.541s 4 2.44x
💻 Local Express 8.778s (-0.8%) 9.025s (-2.7%) 0.247s 4 2.53x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.020s (-9.4% 🟢) 4.797s (~) 1.777s 7 1.00x
▲ Vercel Express 3.241s (+9.9% 🔺) 4.909s (+10.1% 🔺) 1.669s 7 1.07x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 10 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.696s (+21.5% 🔺) 1.004s (-1.7%) 0.308s 60 1.00x
🐘 Postgres Next.js (Turbopack) 0.794s (-1.5%) 1.024s (+1.6%) 0.230s 59 1.14x
🐘 Postgres Nitro 0.811s (-4.0%) 1.007s (~) 0.196s 60 1.17x
🐘 Postgres Express 0.829s (-1.4%) 1.007s (~) 0.178s 60 1.19x
💻 Local Next.js (Turbopack) 0.838s (-1.8%) 1.004s (-1.7%) 0.166s 60 1.20x
💻 Local Express 0.996s (+1.3%) 1.303s (+10.3% 🔺) 0.307s 47 1.43x
💻 Local Nitro 1.007s (+1.9%) 1.506s (+27.5% 🔺) 0.499s 40 1.45x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 10.129s (-1.3%) 11.743s (-4.1%) 1.614s 6 1.00x
▲ Vercel Express 11.804s (+17.6% 🔺) 13.192s (+8.7% 🔺) 1.389s 5 1.17x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 25 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.622s (+25.2% 🔺) 2.006s (~) 0.384s 45 1.00x
🐘 Postgres Nitro 1.901s (-6.4% 🟢) 2.030s (-25.3% 🟢) 0.129s 45 1.17x
🐘 Postgres Next.js (Turbopack) 1.925s (-2.2%) 2.175s (-3.7%) 0.250s 42 1.19x
🐘 Postgres Express 2.032s (+0.5%) 2.737s (+3.7%) 0.705s 33 1.25x
💻 Local Next.js (Turbopack) 2.719s (~) 3.041s (~) 0.322s 30 1.68x
💻 Local Express 3.014s (-0.6%) 3.609s (+0.6%) 0.595s 25 1.86x
💻 Local Nitro 3.022s (~) 3.729s (+3.4%) 0.707s 25 1.86x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 30.342s (-11.5% 🟢) 32.278s (-11.1% 🟢) 1.936s 3 1.00x
▲ Vercel Express 33.242s (-2.1%) 35.187s (-1.2%) 1.945s 3 1.10x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 sequential data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 3.331s (+27.1% 🔺) 4.008s (+31.1% 🔺) 0.677s 30 1.00x
🐘 Postgres Next.js (Turbopack) 3.818s (-2.9%) 4.112s (-3.3%) 0.294s 30 1.15x
🐘 Postgres Nitro 3.925s (-4.3%) 4.217s (-12.4% 🟢) 0.292s 29 1.18x
🐘 Postgres Express 4.057s (-1.6%) 4.666s (-3.8%) 0.609s 26 1.22x
💻 Local Next.js (Turbopack) 8.735s (~) 9.018s (~) 0.283s 14 2.62x
💻 Local Nitro 8.920s (-2.6%) 9.325s (-4.7%) 0.405s 13 2.68x
💻 Local Express 9.189s (~) 9.787s (-2.3%) 0.598s 13 2.76x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 83.215s (-3.8%) 84.748s (-4.3%) 1.534s 2 1.00x
▲ Vercel Nitro 92.340s (+5.2% 🔺) 94.333s (+5.1% 🔺) 1.993s 2 1.11x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 10 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.245s (-7.0% 🟢) 1.009s (~) 0.764s 60 1.00x
🐘 Postgres Nitro 0.276s (-6.5% 🟢) 1.007s (~) 0.731s 60 1.13x
🐘 Postgres Express 0.281s (-4.9%) 1.008s (~) 0.727s 60 1.15x
🌐 Redis Next.js (Turbopack) 0.289s (+8.5% 🔺) 1.004s (~) 0.715s 60 1.18x
💻 Local Nitro 0.572s (-1.2%) 1.004s (~) 0.432s 60 2.34x
💻 Local Next.js (Turbopack) 0.585s (+0.6%) 1.004s (~) 0.420s 60 2.39x
💻 Local Express 0.610s (~) 1.004s (-1.7%) 0.394s 60 2.49x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 1.799s (+3.3%) 3.371s (+1.7%) 1.572s 18 1.00x
▲ Vercel Nitro 1.869s (+10.7% 🔺) 3.390s (~) 1.521s 18 1.04x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Express | Nitro

workflow with 25 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.473s (-5.3% 🟢) 1.008s (~) 0.534s 90 1.00x
🐘 Postgres Nitro 0.481s (-6.8% 🟢) 1.007s (~) 0.526s 90 1.02x
🐘 Postgres Express 0.492s (-6.0% 🟢) 1.008s (~) 0.515s 90 1.04x
🌐 Redis Next.js (Turbopack) 1.185s (+9.8% 🔺) 2.028s (+8.9% 🔺) 0.843s 45 2.50x
💻 Local Nitro 2.393s (-6.2% 🟢) 3.008s (~) 0.615s 30 5.06x
💻 Local Express 2.506s (-1.0%) 3.008s (~) 0.502s 30 5.30x
💻 Local Next.js (Turbopack) 2.631s (~) 3.042s (+1.1%) 0.411s 30 5.56x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 2.927s (-27.9% 🟢) 4.676s (-17.2% 🟢) 1.749s 20 1.00x
▲ Vercel Express 3.285s (+4.6%) 4.701s (-3.7%) 1.416s 20 1.12x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

workflow with 50 concurrent data payload steps (10KB)

💻 Local Development

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
🐘 Postgres 🥇 Next.js (Turbopack) 0.761s (-0.6%) 1.008s (~) 0.246s 120 1.00x
🐘 Postgres Nitro 0.768s (-4.2%) 1.008s (~) 0.240s 120 1.01x
🐘 Postgres Express 0.790s (-3.8%) 1.009s (~) 0.218s 119 1.04x
🌐 Redis Next.js (Turbopack) 2.630s (+1.4%) 3.007s (~) 0.377s 40 3.45x
💻 Local Nitro 10.471s (-6.3% 🟢) 11.027s (-6.2% 🟢) 0.556s 11 13.75x
💻 Local Next.js (Turbopack) 10.931s (~) 11.483s (~) 0.551s 11 14.36x
💻 Local Express 11.194s (-0.6%) 11.754s (-0.8%) 0.561s 11 14.70x

▲ Production (Vercel)

World Framework Workflow Time Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 7.415s (-10.3% 🟢) 8.935s (-11.6% 🟢) 1.520s 14 1.00x
▲ Vercel Express 8.122s (+4.4%) 9.540s (+2.3%) 1.418s 13 1.10x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - -

🔍 Observability: Nitro | Express

Stream Benchmarks (includes TTFB metrics)
workflow with stream

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
💻 Local 🥇 Next.js (Turbopack) 0.170s (-2.9%) 1.002s (~) 0.011s (-4.3%) 1.017s (~) 0.846s 10 1.00x
🌐 Redis Next.js (Turbopack) 0.187s (+33.2% 🔺) 1.001s (~) 0.002s (+30.8% 🔺) 1.008s (~) 0.820s 10 1.10x
🐘 Postgres Express 0.198s (-10.3% 🟢) 0.998s (+0.7%) 0.001s (-14.3% 🟢) 1.011s (~) 0.813s 10 1.16x
🐘 Postgres Next.js (Turbopack) 0.200s (+0.8%) 1.001s (~) 0.001s (+8.3% 🔺) 1.012s (~) 0.812s 10 1.18x
🐘 Postgres Nitro 0.203s (-4.5%) 0.992s (-0.6%) 0.001s (+16.7% 🔺) 1.010s (~) 0.807s 10 1.19x
💻 Local Express 0.210s (+1.4%) 1.004s (~) 0.012s (+0.8%) 1.019s (~) 0.808s 10 1.23x
💻 Local Nitro 0.217s (+6.6% 🔺) 1.003s (~) 0.010s (-6.4% 🟢) 1.016s (~) 0.799s 10 1.27x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 1.715s (+3.4%) 2.777s (-3.3%) 0.767s (+36.8% 🔺) 4.141s (+0.9%) 2.426s 10 1.00x
▲ Vercel Express 1.754s (+1.0%) 2.695s (-13.5% 🟢) 0.489s (-23.4% 🟢) 3.777s (-17.3% 🟢) 2.023s 10 1.02x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

stream pipeline with 5 transform steps (1MB)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.485s (+27.7% 🔺) 1.001s (~) 0.003s (-3.7%) 1.011s (~) 0.526s 60 1.00x
🐘 Postgres Nitro 0.605s (-3.0%) 1.003s (~) 0.006s (+45.9% 🔺) 1.026s (~) 0.421s 59 1.25x
🐘 Postgres Next.js (Turbopack) 0.615s (~) 1.010s (~) 0.004s (-4.4%) 1.023s (~) 0.409s 59 1.27x
🐘 Postgres Express 0.620s (~) 1.002s (~) 0.004s (~) 1.023s (~) 0.403s 59 1.28x
💻 Local Next.js (Turbopack) 0.664s (-1.7%) 1.009s (-1.6%) 0.010s (+8.5% 🔺) 1.024s (-1.5%) 0.359s 59 1.37x
💻 Local Express 0.732s (+0.6%) 1.010s (~) 0.009s (+8.0% 🔺) 1.023s (~) 0.291s 59 1.51x
💻 Local Nitro 0.749s (+2.9%) 1.010s (~) 0.009s (+8.2% 🔺) 1.023s (~) 0.274s 59 1.54x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Express 4.003s (-5.0%) 4.992s (-9.1% 🟢) 0.226s (-54.2% 🟢) 5.758s (-13.1% 🟢) 1.755s 11 1.00x
▲ Vercel Nitro 4.568s (+10.5% 🔺) 5.589s (+4.8%) 0.209s (-11.3% 🟢) 6.490s (+3.4%) 1.922s 10 1.14x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Express | Nitro

10 parallel streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 0.893s (+6.2% 🔺) 1.017s (+1.7%) 0.000s (-49.2% 🟢) 1.021s (+1.7%) 0.129s 59 1.00x
🐘 Postgres Next.js (Turbopack) 0.897s (-8.4% 🟢) 1.072s (-17.8% 🟢) 0.000s (-17.9% 🟢) 1.080s (-17.8% 🟢) 0.183s 56 1.00x
🐘 Postgres Nitro 0.931s (-7.0% 🟢) 1.082s (-20.2% 🟢) 0.000s (-60.0% 🟢) 1.099s (-20.3% 🟢) 0.168s 55 1.04x
🐘 Postgres Express 0.974s (+0.7%) 1.239s (+1.3%) 0.000s (-2.0%) 1.254s (~) 0.280s 49 1.09x
💻 Local Nitro 1.216s (-2.5%) 2.019s (~) 0.000s (-9.1% 🟢) 2.022s (~) 0.806s 30 1.36x
💻 Local Express 1.254s (+0.9%) 2.021s (~) 0.000s (~) 2.023s (~) 0.769s 30 1.41x
💻 Local Next.js (Turbopack) 1.267s (-2.0%) 2.021s (~) 0.000s (~) 2.024s (~) 0.757s 30 1.42x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 3.042s (-9.4% 🟢) 4.208s (-2.0%) 0.000s (NaN%) 4.846s (-3.2%) 1.804s 13 1.00x
▲ Vercel Express 3.081s (-13.0% 🟢) 4.269s (-5.2% 🟢) 0.000s (-100.0% 🟢) 4.906s (-5.7% 🟢) 1.825s 13 1.01x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

fan-out fan-in 10 streams (1MB each)

💻 Local Development

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
🌐 Redis 🥇 Next.js (Turbopack) 1.625s (+4.7%) 2.002s (-1.6%) 0.000s (-100.0% 🟢) 2.006s (-1.6%) 0.381s 30 1.00x
🐘 Postgres Nitro 1.726s (-3.8%) 2.137s (~) 0.000s (~) 2.155s (~) 0.429s 28 1.06x
🐘 Postgres Express 1.766s (-0.6%) 2.102s (-0.9%) 0.000s (NaN%) 2.115s (-2.4%) 0.349s 29 1.09x
🐘 Postgres Next.js (Turbopack) 1.797s (-6.2% 🟢) 2.111s (-1.6%) 0.000s (-50.0% 🟢) 2.156s (~) 0.359s 28 1.11x
💻 Local Nitro 3.374s (-6.6% 🟢) 4.033s (-1.6%) 0.001s (+22.2% 🔺) 4.037s (-1.6%) 0.663s 15 2.08x
💻 Local Next.js (Turbopack) 3.545s (-4.1%) 4.164s (~) 0.000s (-44.4% 🟢) 4.168s (~) 0.623s 15 2.18x
💻 Local Express 3.728s (+7.6% 🔺) 4.101s (+1.7%) 0.001s (+40.0% 🔺) 4.104s (+1.7%) 0.376s 15 2.29x

▲ Production (Vercel)

World Framework Workflow Time TTFB Slurp Wall Time Overhead Samples vs Fastest
▲ Vercel 🥇 Nitro 4.658s (+1.4%) 5.637s (~) 0.000s (~) 6.292s (~) 1.634s 10 1.00x
▲ Vercel Express 5.390s (+22.4% 🔺) 6.374s (+15.9% 🔺) 0.000s (NaN%) 6.917s (+12.2% 🔺) 1.527s 9 1.16x
▲ Vercel Next.js (Turbopack) ⚠️ missing - - - - -

🔍 Observability: Nitro | Express

Summary

Fastest Framework by World

Winner determined by most benchmark wins

World 🥇 Fastest Framework Wins
💻 Local Next.js (Turbopack) 12/21
🐘 Postgres Nitro 11/21
▲ Vercel Nitro 11/21
Fastest World by Framework

Winner determined by most benchmark wins

Framework 🥇 Fastest World Wins
Express 🐘 Postgres 17/21
Next.js (Turbopack) 🌐 Redis 9/21
Nitro 🐘 Postgres 18/21
Column Definitions
  • Workflow Time: Runtime reported by workflow (completedAt - createdAt) - primary metric
  • TTFB: Time to First Byte - time from workflow start until first stream byte received (stream benchmarks only)
  • Slurp: Time from first byte to complete stream consumption (stream benchmarks only)
  • Wall Time: Total testbench time (trigger workflow + poll for result)
  • Overhead: Testbench overhead (Wall Time - Workflow Time)
  • Samples: Number of benchmark iterations run
  • vs Fastest: How much slower compared to the fastest configuration for this benchmark

Worlds:

  • 💻 Local: In-memory filesystem world (local development)
  • 🐘 Postgres: PostgreSQL database world (local development)
  • ▲ Vercel: Vercel production/preview deployment
  • 🌐 Turso: Community world (local development)
  • 🌐 MongoDB: Community world (local development)
  • 🌐 Redis: Community world (local development)
  • 🌐 Jazz: Community world (local development)

📋 View full workflow run


Some benchmark jobs failed:

  • Local: success
  • Postgres: success
  • Vercel: failure

Check the workflow run for details.

@VaguelySerious VaguelySerious marked this pull request as ready for review April 2, 2026 17:42
@VaguelySerious VaguelySerious requested a review from a team as a code owner April 2, 2026 17:42
Copy link
Copy Markdown
Contributor

@karthikscale3 karthikscale3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review: Approve — the fix is correct, minimal, and low-risk. Three observations:

  1. Dead code in world-vercel/src/queue.ts: After this change, the v3 fallback check (typeof MessageWrapper.encode === 'function') will always be true since MessageWrapper is now created with v4's z. The fallback path is dead code — cleanup opportunity.

  2. Broader inconsistency: @workflow/world has only queue.ts using zod/v4 while all other files use zod v3 compat. If more files migrate to v4-only features in the future, the same class of mismatch bug could recur. Worth considering a lint rule or a comment warning consumers.

  3. Regression test is good — directly validates that v4-native schemas compose correctly with v4's z.object(), which is the exact scenario that was broken.

@VaguelySerious
Copy link
Copy Markdown
Member Author

Zod compat testing results

Checked out the branch, built and tarballed the workflow package, then created a fresh Next.js project with zod@3 to test various configurations.

Normal setups: no issue

Under standard pnpm, pnpm + shamefully-hoist, and npm, @workflow/world-local always resolves its own zod@4.3.6 (v4 native). Since import z from 'zod' from zod@4.3.6 gives native v4 — matching the v4 schemas from @workflow/world/queue.ts — there's no mismatch. The bug cannot reproduce without extra configuration.

Package Manager world-local resolves zod to Mismatch?
pnpm (strict) zod@4.3.6 (own dep, isolated) No
pnpm + shamefully-hoist zod@4.3.6 (virtual store respects version constraints) No
npm zod@4.3.6 (nested, incompatible semver) No

Reproducible with pnpm.overrides

Adding pnpm.overrides: { "zod": "3.25.76" } forces all packages to use the user's zod. In zod@3.25.76:

  • import z from 'zod'v3 compat (has _parse)
  • import { z } from 'zod/v4'v4 native (has _zod)

This triggers the crash in the pre-fix code at world-local/dist/queue.js:174:

import z from 'zod';                                       // → v3 compat
import { ValidQueueName, MessageId } from '@workflow/world'; // → v4 native

const HeaderParser = z.object({
    'x-vqs-queue-name': ValidQueueName,  // v4 schema, no _parse → 💥
    'x-vqs-message-id': MessageId,
    'x-vqs-message-attempt': z.coerce.number(),
});
HeaderParser.safeParse(...)  // TypeError: keyValidator._parse is not a function

The PR fix handles the override scenario correctly

With the fix applied (import { z } from 'zod/v4'), even under pnpm.overrides, both @workflow/world and world-local use zod/v4 from the same zod@3.25.76 package → same v4 engine → no mismatch. Verified end-to-end: createLocalWorld()createQueueHandler() → HTTP request parsing all work.

Note: only queue schemas are affected

In @workflow/world, only queue.ts uses zod/v4 explicitly. All other source files (events.ts, runs.ts, hooks.ts) use import { z } from 'zod', so they follow whatever version the consumer provides and stay in sync. The queue schemas (ValidQueueName, MessageId, QueuePayloadSchema) are the only ones that are always v4 native regardless of resolution — which is why this PR correctly targets only the queue-related files.

@VaguelySerious VaguelySerious merged commit ef2218a into main Apr 2, 2026
103 of 105 checks passed
@VaguelySerious VaguelySerious deleted the peter/issue-1587 branch April 2, 2026 19:38
@ghost ghost mentioned this pull request Apr 2, 2026
pranaygp added a commit that referenced this pull request Apr 3, 2026
…1-refresh

* origin/main: (21 commits)
  Fix node-module-error plugin matching identifiers in multi-line comments (#1554)
  fix(swc-plugin): use binding name for class expression method registrations (#1599)
  fix(builders): override `sideEffects: false` for discovered workflow/step/serde entries (#1598)
  [world-vercel] align header names to `x-vercel-workflow-*` convention (#1602)
  [docs] Add vercel world consumer function security documentation (#1543)
  Make `start()` types `unknown` when `deploymentId` is provided (#1367)
  fix(next): stop force-setting WORKFLOW_PUBLIC_MANIFEST=1 during next dev (#1597)
  Version Packages (beta) (#1593)
  [docs] Tidy world API docs and document new stream helpers (#1581)
  Rename 'Workflow Development Kit' / 'DevKit' to 'Workflow SDK' (#1595)
  [world] Use zod/v4 in queue files to match @workflow/world schemas (#1588)
  [ai] Fix fatal stream errors surfacing as [object Object] (#1589)
  [web] Fix server crash on unmatched routes (#1590)
  docs: rename 'Complex Example' to 'Instance Methods as Steps' (#1592)
  Version Packages (beta) (#1563)
  [core] Extend flow route duration to "max" and fail runs where replay takes too long (#1567)
  fix: check target run capabilities before encrypting hook payloads (#1572)
  [core] Combine initial run fetch, event fetch, and run_started event creation (#1569)
  [docs] Split World API docs into sub-pages, update skill.md (#1457)
  [nitro] Preserve workflow step registration side effects (#1386)
  ...

# Conflicts:
#	skills/workflow/SKILL.md
@ghost ghost mentioned this pull request Apr 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

2 participants