Skip to content

fix(core): guard extractStreamIds against circular references#2687

Open
Osamaali313 wants to merge 1 commit into
vercel:mainfrom
Osamaali313:fix/extract-stream-ids-circular
Open

fix(core): guard extractStreamIds against circular references#2687
Osamaali313 wants to merge 1 commit into
vercel:mainfrom
Osamaali313:fix/extract-stream-ids-circular

Conversation

@Osamaali313

Copy link
Copy Markdown

Bug

extractStreamIds (packages/core/src/serialization-format.ts) recursively walks arrays and objects with no cycle guard:

function traverse(value: unknown): void {
  if (isStreamId(value)) streamIds.push(value as string);
  else if (Array.isArray(value)) { for (const item of value) traverse(item); }
  else if (value && typeof value === 'object') { for (const val of Object.values(value)) traverse(val); }
}

The data it walks is hydrated observability data produced by devalue, which explicitly preserves circular and repeated references (see hydrateDatadevalue.parse/unflatten). So a workflow step that returns a self-referential value (e.g. const o = {}; o.self = o; return o;) serializes fine, lands in the event log, and later crashes the inspection paths that call extractStreamIdswf inspect (packages/cli/src/lib/inspect/hydration.ts) and the web dashboard (packages/web-shared/src/lib/hydration.ts) — with RangeError: Maximum call stack size exceeded.

Reproduction (real code, vitest)

Two new tests fail on main with RangeError: Maximum call stack size exceeded and pass after the fix:

RED  (unpatched): extractStreamIds > circular references … RangeError: Maximum call stack size exceeded  (2 failed)
GREEN (patched):  2 passed

(Confirmed devalue round-trips a cycle: dv.parse(dv.stringify(a)) with a.self = a yields round.self === round.)

Fix

Track visited containers in a WeakSet and skip already-seen ones. Behavior for acyclic inputs is unchanged (result de-duplication unaffected).

Test

Adds object-cycle and array-cycle regression tests to serialization-format.test.ts (describe('extractStreamIds')). Includes a changeset (@workflow/core patch). Commit is DCO signed-off and signed (Verified).

extractStreamIds recursively walks arrays/objects with no cycle guard. The hydrated observability data it traverses is produced by devalue, which preserves circular and repeated references, so a workflow step returning a self-referential value lands in the event log and later crashes the inspection paths (wf inspect CLI and the web dashboard) with RangeError: Maximum call stack size exceeded.

Track visited containers in a WeakSet and skip already-seen ones. Behavior for acyclic inputs is unchanged. Adds regression tests for object and array cycles.

Signed-off-by: Osamaali313 <86572800+Osamaali313@users.noreply.github.com>
@Osamaali313 Osamaali313 requested review from a team and ijjk as code owners June 27, 2026 21:02
Copilot AI review requested due to automatic review settings June 27, 2026 21:02
@changeset-bot

changeset-bot Bot commented Jun 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: ffdd4b4

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@vercel

vercel Bot commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

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

A member of the Team first needs to authorize it.

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.

2 participants