Skip to content

[core] Forward-port: don't flag wait_completed.resumeAt mismatch without a recorded value (#2177)#2186

Open
VaguelySerious wants to merge 1 commit into
peter/forward-port-2171-mainfrom
peter/forward-port-2177-main
Open

[core] Forward-port: don't flag wait_completed.resumeAt mismatch without a recorded value (#2177)#2186
VaguelySerious wants to merge 1 commit into
peter/forward-port-2171-mainfrom
peter/forward-port-2177-main

Conversation

@VaguelySerious
Copy link
Copy Markdown
Member

Forward-port of #2177 from stable to main.

Note

Stacked on #2185 (the forward-port of #2171). 2177's sleep.ts changes build directly on 2171's runtime changes (shared wait_completed consumer and awaitEarlierDeliveries/registerDeliveryBarrier imports), so this PR is based on the 2171 forward-port branch. Retarget to main once #2185 merges. The diff shown here is 2177's contribution only.

Summary

Fixes a second, independent source of CORRUPTED_EVENT_LOG on replay: a wait_completed whose resumeAt is validated against a non-deterministic, wall-clock-derived value, producing a false corruption error on a perfectly consistent event log.

sleep(<ms|string>) computes resumeAt = Date.now() + duration. On replay the VM clock advances to each event's createdAt, so a freshly-created sleep recomputes a different absolute resumeAt. This is normally overwritten by the recorded value via wait_created — but when a wait_completed is consumed by a sleep consumer that never applied a wait_created (hasCreatedEvent=false), the queue item still holds the recomputed value and the comparison falsely fails.

Fix: only validate resumeAt when an authoritative recorded value is available (hasCreatedEvent=true); otherwise the correlationId match already establishes identity, so skip the check. Validation extracted into detectResumeAtMismatch.

See #2177 for full root-cause analysis (incl. production instrumentation data).

Validation

  • Applied 2177's net diff (stable...head, which already excludes 2171) onto the 2171 forward-port branch — clean, content-identical to the original PR.
  • @workflow/core typecheck: clean.
  • sleep, hook-sleep-interaction, async-deserialization-ordering tests: 58/58 pass (incl. the new hasCreatedEvent=false regression test).

Co-Authored-By: Claude Opus 4.8 noreply@anthropic.com

…rded value

Forward-port of #2177 from stable to main.

A reused/duration sleep races a `wait_completed` replay against a
non-deterministic, wall-clock-derived expected value, producing a false
CorruptedEventLogError on a perfectly consistent event log.

`sleep(<ms|string>)` computes its resumeAt as `Date.now() + duration`. The
original run records that absolute timestamp into both wait_created and
wait_completed. During replay the VM clock advances to each event's createdAt,
so a freshly-created sleep recomputes a different absolute resumeAt. Normally
harmless: the wait_created consumer overwrites the queue item's resumeAt with
the recorded (authoritative) value before wait_completed is validated.

The bug: when a wait_completed is consumed by a sleep consumer that never
applied a wait_created (hasCreatedEvent=false), the queue item still holds the
freshly-recomputed value, and the resumeAt comparison fails — even though the
event log is internally consistent and the recorded resumeAt is the source of
truth.

Fix: only validate resumeAt when an authoritative recorded value is available
(hasCreatedEvent=true). When it is not, the correlationId match already
establishes the wait's identity, so skip the check. Extracted into
`detectResumeAtMismatch`.

Co-Authored-By: Nathan Rajlich <n@n8.io>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@VaguelySerious VaguelySerious requested a review from a team as a code owner May 31, 2026 09:10
@changeset-bot
Copy link
Copy Markdown

changeset-bot Bot commented May 31, 2026

🦋 Changeset detected

Latest commit: b1855a1

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

This PR includes changesets to release 16 packages
Name Type
@workflow/core Patch
@workflow/builders Patch
@workflow/cli Patch
@workflow/next Patch
@workflow/nitro Patch
@workflow/vitest Patch
@workflow/web-shared Patch
@workflow/web Patch
workflow Patch
@workflow/world-testing 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 May 31, 2026

🧪 E2E Test Results

Some tests failed

Summary

Passed Failed Skipped Total
❌ ▲ Vercel Production 1261 5 219 1485
✅ 💻 Local Development 1671 0 219 1890
❌ 📦 Local Production 1670 1 219 1890
✅ 🐘 Local Postgres 1671 0 219 1890
✅ 🪟 Windows 135 0 0 135
❌ 📋 Other 768 1 176 945
Total 7176 7 1052 8235

❌ Failed Tests

▲ Vercel Production (5 failed)

fastify (2 failed):

nextjs-turbopack (1 failed):

  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step

nuxt (2 failed):

  • promiseAnyWorkflow | wrun_01KSYMXKT2DE5YN8JC0T5ZAW5F | 🔍 observability
  • AbortController abortFromStepWorkflow: step abort cancels an in-flight sibling step
📦 Local Production (1 failed)

hono-stable (1 failed):

  • AbortController abortThrowIfAbortedWorkflow: throwIfAborted causes FatalError, no retries
📋 Other (1 failed)

e2e-local-prod-nest-stable (1 failed):

  • hookWithSleepFinalStepWorkflow - step only on final payload | wrun_01KSYNDYFZ0DK3RA01BW7D5X5Q

Details by Category

❌ ▲ Vercel Production
App Passed Failed Skipped
✅ astro 109 0 26
✅ example 109 0 26
✅ express 109 0 26
❌ fastify 107 2 26
✅ hono 109 0 26
❌ nextjs-turbopack 132 1 2
✅ nextjs-webpack 133 0 2
✅ nitro 109 0 26
❌ nuxt 107 2 26
✅ sveltekit 128 0 7
✅ vite 109 0 26
✅ 💻 Local Development
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
❌ 📦 Local Production
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
❌ hono-stable 109 1 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🐘 Local Postgres
App Passed Failed Skipped
✅ astro-stable 110 0 25
✅ express-stable 110 0 25
✅ fastify-stable 110 0 25
✅ hono-stable 110 0 25
✅ nextjs-turbopack-canary 116 0 19
✅ nextjs-turbopack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-turbopack-stable-lazy-discovery-enabled 135 0 0
✅ nextjs-webpack-canary 116 0 19
✅ nextjs-webpack-stable-lazy-discovery-disabled 135 0 0
✅ nextjs-webpack-stable-lazy-discovery-enabled 135 0 0
✅ nitro-stable 110 0 25
✅ nuxt-stable 110 0 25
✅ sveltekit-stable 129 0 6
✅ vite-stable 110 0 25
✅ 🪟 Windows
App Passed Failed Skipped
✅ nextjs-turbopack 135 0 0
❌ 📋 Other
App Passed Failed Skipped
✅ e2e-local-dev-nest-stable 110 0 25
✅ e2e-local-dev-tanstack-start- 110 0 25
✅ e2e-local-postgres-nest-stable 110 0 25
✅ e2e-local-postgres-tanstack-start- 110 0 25
❌ e2e-local-prod-nest-stable 109 1 25
✅ e2e-local-prod-tanstack-start- 110 0 25
✅ e2e-vercel-prod-tanstack-start 109 0 26

📋 View full workflow run


Some E2E test jobs failed:

  • Vercel Prod: failure
  • Local Dev: success
  • Local Prod: failure
  • Local Postgres: success
  • Windows: success

Check the workflow run for details.

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 31, 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 May 31, 2026 9:14am
example-nextjs-workflow-webpack Ready Ready Preview, Comment May 31, 2026 9:14am
example-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-astro-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-express-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-fastify-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-hono-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-nitro-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-nuxt-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-sveltekit-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-tanstack-start-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workbench-vite-workflow Ready Ready Preview, Comment May 31, 2026 9:14am
workflow-docs Ready Ready Preview, Comment, Open in v0 May 31, 2026 9:14am
workflow-swc-playground Ready Ready Preview, Comment May 31, 2026 9:14am
workflow-tarballs Ready Ready Preview, Comment May 31, 2026 9:14am
workflow-web Ready Ready Preview, Comment May 31, 2026 9:14am

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.

1 participant