Skip to content

Fix compatibility with Zod 4.4.x#1902

Merged
TooTallNate merged 3 commits into
vercel:mainfrom
ziyak97:main
May 4, 2026
Merged

Fix compatibility with Zod 4.4.x#1902
TooTallNate merged 3 commits into
vercel:mainfrom
ziyak97:main

Conversation

@ziyak97
Copy link
Copy Markdown
Contributor

@ziyak97 ziyak97 commented May 2, 2026

I have mentioned this issue here -> #1901

Turns out from release 4.4.0, Zod now treats a property whose schema is z.undefined() as required.

To fix this I have explicitly made them optional.

Ref -> Required object properties with z.undefined() in -> #1901

@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 2, 2026

⚠️ No Changeset found

Latest commit: fe5d16a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

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

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 2, 2026

@ziyak97 is attempting to deploy a commit to the Vercel Labs Team on Vercel.

A member of the Team first needs to authorize it.

@TooTallNate
Copy link
Copy Markdown
Member

Seems like this was a bug introduced in Zod v4.4.0, but was fixed upstream in v4.4.2, so I don't think implementing the workaround in this repo is necessary. Thank you for bringing this up anyways though.

@TooTallNate TooTallNate closed this May 3, 2026
@ziyak97
Copy link
Copy Markdown
Contributor Author

ziyak97 commented May 3, 2026

@TooTallNate

This was a bug introduced in Zod v4.4.0, but was fixed upstream in v4.4.2 -> this is not true.

I have updated to v4.4.2 and still get this issue.

The bug is on Workflows side.

Kets like -> error: z.undefined().optional() -> are not just expected to be undefined, they are not expected to exist in the first place. Prior to v4.4.0, this behavior was allowed on Zods side (a bug on their part), but fixed from v4.4.2 onwards.

I think you have referenced a similar thread I had seen earlier, but they have since clarified that this is an expected breaking change from v4.4.x onwards.

Sharing a ref to the - colinhacks/zod#5917 (comment)

Almost every single one of my workflows are failing due to this (I tried on Zod v4.4.2 as well)

@TooTallNate TooTallNate reopened this May 4, 2026
@TooTallNate
Copy link
Copy Markdown
Member

Ok thanks for clarifying. I've re-opened and we will confirm the issue you're describing.

Copy link
Copy Markdown
Member

@TooTallNate TooTallNate left a comment

Choose a reason for hiding this comment

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

Verified the bug and the fix empirically. The Zod 4.4 regression is real (confirmed against zod@4.4.3, latest published) and the issue at colinhacks/zod#5917 captures the upstream behavior change for .optional() interactions with other primitives — it's marked bug and Closed, but the in-the-wild compatibility hazard is here regardless.

The repo's workspace pin is zod: 4.3.6, but zod is a peerDependencies of @workflow/world (and the catalog version is the floor), so consumer apps can — and do — resolve the SDK against any 4.x. A user on 5.0.0-beta-4 with their own zod@4.4.2 resolution hits the bug as soon as the SDK tries to deserialize a wire payload for a non-terminal run.

Verified the fix doesn't compromise validation: z.undefined().optional() accepts both missing properties and explicit-undefined, but still rejects properties with non-undefined values:

missing output:    true
explicit undefined: true
with output value: false   ← still rejected ✓

So the loosening is purely along the "must be explicitly set to undefined" axis — which no real wire producer was doing — and the variant discriminator remains intact.

Comprehensive: this is the only file in the codebase using z.undefined() (grep -rn "z\.undefined\(\)" packages --include="*.ts" confirms). All seven occurrences are in runs.ts and all seven are fixed.

One follow-up suggestion (non-blocking)

The repo's pnpm-workspace.yaml pins zod: 4.3.6, which means CI will continue to build/test against the version that doesn't have this regression — so this fix is unverified in CI. Worth bumping the catalog to 4.4.3 (or ^4.4.0) in a follow-up so future regressions in this class show up locally instead of in user reports. Adding a small runs.test.ts that asserts the schema accepts { status: 'running' } without output/error/completedAt would also be a cheap regression gate.

Thanks for the investigation work in #1901 — clear repro, root-caused, upstream issue linked. Easy approve.

@TooTallNate
Copy link
Copy Markdown
Member

Thanks for the fix — the change is good to merge, but there's one merge blocker: this repo requires verified signatures on commits, and your commits here are currently unsigned (verified: false).

The easiest setup is SSH signing — uses the same key you already have on GitHub for git push:

# One-time global config
git config --global gpg.format ssh
git config --global user.signingkey ~/.ssh/id_ed25519.pub  # path to the pubkey GitHub knows
git config --global commit.gpgsign true

You also need to register that key as a signing key (separate from the auth key) at https://github.com/settings/ssh/new — choose "Signing Key" as the type. (If you only have one SSH key already configured for auth, GitHub lets the same public key be registered under both types.)

Then on this branch, re-sign your existing two commits:

git rebase --exec 'git commit --amend --no-edit -S' main
git push --force-with-lease

Full GitHub docs: https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification

If you'd rather not deal with the signing setup, let me know and I can re-author the patch on a signed branch with credit to you in the commit message.

@ziyak97 ziyak97 force-pushed the main branch 2 times, most recently from 6a819a9 to b8d309f Compare May 4, 2026 09:39
@ziyak97
Copy link
Copy Markdown
Contributor Author

ziyak97 commented May 4, 2026

Thanks @TooTallNate i have signed the commit

@TooTallNate
Copy link
Copy Markdown
Member

TooTallNate commented May 4, 2026

Apologies — I should have flagged DCO upfront when you first asked about the signing failure. The two checks share the word "sign" but are independent, and I only mentioned cryptographic signing in my earlier comment. That left you to bounce off DCO as a second hurdle, which is on me.

The signing fix worked — your commit is now verified: true. The remaining DCO failure is a separate check: it requires every commit to include a Signed-off-by: trailer in the commit message body (this is the Developer Certificate of Origin, distinct from cryptographic signing).

The DCO bot provides a fix that doesn't require another rebase. Just add a normal commit with this exact message body:

git commit --allow-empty -m "DCO Remediation Commit for Ziyak <ziyak97@gmail.com>" \
  -m "I, Ziyak <ziyak97@gmail.com>, hereby add my Signed-off-by to this commit: 2bf58718e66abcb8dc66d03d4de6bbbcf5bb1f67" \
  -m "Signed-off-by: Ziyak <ziyak97@gmail.com>" \
  -s
git push

Note the -s flag at the end — that adds the Signed-off-by: trailer automatically based on your git config user.name / user.email (which you've already configured for signing).

Going forward, you can use git commit -s (instead of plain git commit) on every commit and the trailer will be added automatically. Or set it as the default with:

git config --global format.signoff true

After the remediation commit is pushed, the DCO check should turn green and this will be ready to merge.

I, Ziyak <ziyak97@gmail.com>, hereby add my Signed-off-by to this commit: 2bf5871

Signed-off-by: Ziyak <ziyak97@gmail.com>
@ziyak97
Copy link
Copy Markdown
Contributor Author

ziyak97 commented May 4, 2026

Done @TooTallNate

Signed-off-by: Nathan Rajlich <n@n8.io>
@TooTallNate
Copy link
Copy Markdown
Member

Merged, thank you @ziyak97 and sorry for the logistical back and forth.

pranaygp added a commit that referenced this pull request May 5, 2026
* origin/main:
  [core] Skip inline step execution when suspension also has a wait (#1924)
  [errors] Replace chalk import in @workfow/errors with inline ANSI shim (#1915)
  Fix compatibility with Zod 4.4.x (#1902)
  Serialize `run_failed`/`step_failed` errors through serialization pipeline (#1851)
  tarballs: redesign preview tarballs index page (#1911)
  Remove extra changeset (#1922)
  Add stable Next.js eager and lazy test coverage (#1747)
  Enforce per-(run, correlation) uniqueness for entity-creating events in world-postgres (#1878)
  fix(world-vercel): add default request timeout to workflow-server HTTP calls (#1807)
@pranaygp
Copy link
Copy Markdown
Contributor

pranaygp commented May 5, 2026

@TooTallNate does this need to be backported to 4.x?

pranaygp added a commit that referenced this pull request May 5, 2026
…ignal

* origin/main:
  [core] Skip inline step execution when suspension also has a wait (#1924)
  [errors] Replace chalk import in @workfow/errors with inline ANSI shim (#1915)
  Fix compatibility with Zod 4.4.x (#1902)
  Serialize `run_failed`/`step_failed` errors through serialization pipeline (#1851)
  tarballs: redesign preview tarballs index page (#1911)
  Remove extra changeset (#1922)
  Add stable Next.js eager and lazy test coverage (#1747)
  Enforce per-(run, correlation) uniqueness for entity-creating events in world-postgres (#1878)
  fix(world-vercel): add default request timeout to workflow-server HTTP calls (#1807)
  Allow disabling step sourcemap with new `sourcemap` option in builders (#1842)
  [ci] Enable Vercel-prod e2e for tanstack-start (#1904)
  web: configure vercelPreset() for Vercel deployments (#1815)
  [core] Combine flow+step bundle and process steps eagerly (#1338)
  [world-vercel] Revert stream close control framing (#1891)
  [tarballs] Use turbo to build workspace deps before packing (#1908)

# Conflicts:
#	packages/core/src/runtime/step-handler.test.ts
#	packages/core/src/runtime/step-handler.ts
#	packages/core/src/runtime/suspension-handler.ts
#	packages/core/src/step.test.ts
#	packages/world-local/src/storage/events-storage.ts
#	packages/world-postgres/src/drizzle/migrations/meta/_journal.json
@TooTallNate TooTallNate added backport-stable Cherry-pick this PR to the stable branch when merged and removed backport-stable Cherry-pick this PR to the stable branch when merged labels May 5, 2026
@TooTallNate TooTallNate added backport-stable Cherry-pick this PR to the stable branch when merged labels May 5, 2026
github-actions Bot added a commit that referenced this pull request May 5, 2026
* Fix compatibility with Zod 4.4.x

* DCO Remediation Commit for Ziyak <ziyak97@gmail.com>

I, Ziyak <ziyak97@gmail.com>, hereby add my Signed-off-by to this commit: 2bf5871

Signed-off-by: Ziyak <ziyak97@gmail.com>

---------

Signed-off-by: Ziyak <ziyak97@gmail.com>
Signed-off-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Nathan Rajlich <n@n8.io>
Signed-off-by: Ziyak Jehangir <53836911+ziyak97@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 5, 2026

Backport PR opened against stable: #1938. Merge conflicts were resolved by AI — please review carefully.

TooTallNate added a commit that referenced this pull request May 5, 2026
PR #1902 landed without a changeset; this adds the missing patch-level changeset for @workflow/world to the backport branch.
TooTallNate added a commit that referenced this pull request May 5, 2026
…rld (#1939)

PR #1902 landed without a changeset. This adds the missing patch-level
changeset for @workflow/world describing the WorkflowRunSchema
`.optional()` fix needed for Zod 4.4.x compatibility.
TooTallNate added a commit that referenced this pull request May 5, 2026
* Fix compatibility with Zod 4.4.x (#1902)

* Fix compatibility with Zod 4.4.x

* DCO Remediation Commit for Ziyak <ziyak97@gmail.com>

I, Ziyak <ziyak97@gmail.com>, hereby add my Signed-off-by to this commit: 2bf5871

Signed-off-by: Ziyak <ziyak97@gmail.com>

---------

Signed-off-by: Ziyak <ziyak97@gmail.com>
Signed-off-by: Nathan Rajlich <n@n8.io>
Co-authored-by: Nathan Rajlich <n@n8.io>
Signed-off-by: Ziyak Jehangir <53836911+ziyak97@users.noreply.github.com>

* Add missing changeset for Zod 4.4.x compatibility fix

PR #1902 landed without a changeset; this adds the missing patch-level changeset for @workflow/world to the backport branch.

---------

Signed-off-by: Ziyak <ziyak97@gmail.com>
Signed-off-by: Nathan Rajlich <n@n8.io>
Signed-off-by: Ziyak Jehangir <53836911+ziyak97@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Nathan Rajlich <n@n8.io>
pontusab added a commit to cursor/community-plugins that referenced this pull request May 12, 2026
- Switch runSecurityAgent from the Cursor cloud runtime to local
  runtime. Clone the submitted public repo to /tmp via `git clone
  --depth=1 --single-branch --filter=blob:limit=10m`, run the agent
  against it with `local: { cwd }`, clean up in a finally. The cloud
  runtime requires the Cursor GitHub App to be installed on each
  scanned repo, which can't work for a public marketplace where
  authors submit arbitrary repos we don't own. Clone failures
  degrade to a non-fatal manual-review verdict instead of crashing
  the workflow.

- Patch @workflow/world@4.1.1 with the upstream Zod 4.4.x fix
  (vercel/workflow#1902) so workflow runs can persist state under
  our pinned zod@4.4.3. The local storage round-trips through
  JSON.stringify (which strips undefined keys), and zod@4.4.x's
  strict treatment of z.undefined() then rejects the read. Drop the
  patch once a fixed @workflow/world release lands on npm.

- Sync apps/cursor/.env.example to what the code actually reads:
  add CURSOR_API_KEY, GITHUB_TOKEN, NEXT_PUBLIC_OPENPANEL_CLIENT_ID;
  drop unused MCP_OWNER_ID and NEXT_PUBLIC_APP_URL.

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport-stable Cherry-pick this PR to the stable branch when merged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants