Skip to content

fix(codemode): dispose dynamic worker and entrypoint stub after execute#1814

Merged
threepointone merged 1 commit into
mainfrom
fix/codemode-dispose-dynamic-worker
Jun 25, 2026
Merged

fix(codemode): dispose dynamic worker and entrypoint stub after execute#1814
threepointone merged 1 commit into
mainfrom
fix/codemode-dispose-dynamic-worker

Conversation

@threepointone

@threepointone threepointone commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes a flaky @cloudflare/think workers-test failure that surfaces in CI as an uncatchable "Worker exited unexpectedly" (example release run). The underlying crash is a fatal workerd assertion during isolate teardown:

*** Fatal uncaught kj::Exception: workerd/jsg/setup.c++:235: failed:
    expected queueState == QueueState::ACTIVE [1 == 0];
    tried to defer destruction during isolate shutdown; queueState = 1
⎯ Unhandled Errors ⎯  Caused by: Error: Worker exited unexpectedly
Test Files  40 passed (41)

40 passed (41) = every assertion passed, but one file's worker process died before reporting, so vitest reds the whole run. Because it's a process crash (not an assertion failure or timeout), the suite's existing retry: 3 / teardownTimeout: 60_000 can't catch it.

Root cause

DynamicWorkerExecutor.execute() spins up a child Worker via loader.load() and gets an RPC Fetcher stub via getEntrypoint(), but left both for the garbage collector. These own native handles; when one is finalized late (e.g. during isolate shutdown under @cloudflare/vitest-pool-workers) workerd trips the deferred-destruction assertion and kills the worker. The milder, nondeterministic manifestation of the same leak is workerd's An RPC result was not disposed properly warning, which I also observed in the @cloudflare/codemode suite.

This is the only production loader.load() / getEntrypoint() call site in the repo; @cloudflare/shell reuses this same executor, so both are covered.

Fix

Dispose the entrypoint stub and the loaded worker in finally blocks (best-effort via Symbol.dispose), releasing the handles while the isolate is still alive. No behavior or API change for callers.

Test plan

  • pnpm run typecheck (all 113 projects)
  • oxlint clean on executor.ts
  • @cloudflare/codemode suite passes; runtime tests run clean (no RPC-not-disposed warning)
  • Repro before fix: full @cloudflare/think test:workers crashed ~1-in-2 full runs
  • Validation in progress: looping the full test:workers suite with the rebuilt codemode (iter 1 = 41 passed (41), no crash)

Note: dependency bumps (workerd / @cloudflare/vitest-pool-workers) will be handled separately and should further harden this teardown path.

Made with Cursor


Open in Devin Review

DynamicWorkerExecutor.execute() spins up a child Worker via loader.load()
and an RPC Fetcher stub via getEntrypoint(), but left both for GC. When a
native handle is finalized late (e.g. during isolate shutdown under
@cloudflare/vitest-pool-workers) workerd raises a fatal assertion ("tried
to defer destruction during isolate shutdown") that kills the worker,
surfacing as a flaky "Worker exited unexpectedly" with no failing
assertion. The milder manifestation is workerd's "An RPC result was not
disposed properly" warning.

Dispose the entrypoint stub and the loaded worker in finally blocks
(best-effort via Symbol.dispose) so the handles are released while the
isolate is still alive. No behavior or API change for callers.

Co-authored-by: Cursor <cursoragent@cursor.com>
@changeset-bot

changeset-bot Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: e956b69

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

This PR includes changesets to release 1 package
Name Type
@cloudflare/codemode 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

@devin-ai-integration devin-ai-integration Bot 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@pkg-pr-new

pkg-pr-new Bot commented Jun 25, 2026

Copy link
Copy Markdown

Open in StackBlitz

agents

npm i https://pkg.pr.new/agents@1814

@cloudflare/ai-chat

npm i https://pkg.pr.new/@cloudflare/ai-chat@1814

@cloudflare/codemode

npm i https://pkg.pr.new/@cloudflare/codemode@1814

create-think

npm i https://pkg.pr.new/create-think@1814

hono-agents

npm i https://pkg.pr.new/hono-agents@1814

@cloudflare/shell

npm i https://pkg.pr.new/@cloudflare/shell@1814

@cloudflare/think

npm i https://pkg.pr.new/@cloudflare/think@1814

@cloudflare/voice

npm i https://pkg.pr.new/@cloudflare/voice@1814

@cloudflare/worker-bundler

npm i https://pkg.pr.new/@cloudflare/worker-bundler@1814

commit: e956b69

@threepointone threepointone merged commit a79144d into main Jun 25, 2026
5 checks passed
@threepointone threepointone deleted the fix/codemode-dispose-dynamic-worker branch June 25, 2026 13:35
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