Environment
- wrangler: 4.75.0
- miniflare: 4.20260317.0
- @cloudflare/vitest-pool-workers: 0.13.2
- compatibility_date: 2025-01-13
- compatibility_flags:
["nodejs_compat"]
- Platform: macOS (Darwin 25.1.0), Node.js v22.13.1
Describe the Bug
When running vitest tests that use worker_loaders binding to create many ephemeral isolates (40+ per test file via loader.load()), workerd intermittently crashes during isolate teardown with:
*** 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
This appears to be a race condition where a JS callback in the ephemeral isolate tries to call deferDestruction() after the isolate has already entered the DROPPING (1) state in its dropWrappers() shutdown phase.
The crash is probabilistic — roughly 1 in 5 runs in our test suite. It does not affect test correctness (all assertions pass before the crash), but it causes workerd to exit unexpectedly, sometimes preventing vitest from collecting the last few test results.
Minimal Reproduction
wrangler.test.jsonc:
vitest.workers.config.ts:
import { cloudflareTest } from '@cloudflare/vitest-pool-workers'
import { defineConfig } from 'vitest/config'
export default defineConfig({
plugins: [cloudflareTest({ wrangler: { configPath: './wrangler.test.jsonc' } })],
test: {
include: ['src/repro.test.ts'],
dangerouslyIgnoreUnhandledErrors: true,
},
})
src/repro.test.ts:
import { env } from 'cloudflare:workers'
import { describe, expect, it } from 'vitest'
describe('Worker Loader isolate teardown crash', () => {
for (let i = 0; i < 50; i++) {
it(`ephemeral isolate #${i}`, async () => {
const worker = env.LOADER.load({
compatibilityDate: '2025-01-13',
compatibilityFlags: ['nodejs_compat'],
mainModule: 'sandbox.js',
modules: {
'sandbox.js': `
import { WorkerEntrypoint } from 'cloudflare:workers';
export default class extends WorkerEntrypoint {
async evaluate() { return { value: ${i} }; }
}`,
},
})
const ep = worker.getEntrypoint()
const result = await ep.evaluate()
expect(result.value).toBe(i)
})
}
})
Run 5 times — at least 1 will crash:
for i in $(seq 5); do npx vitest run --config vitest.workers.config.ts 2>&1 | grep -E "Tests|Errors|Fatal"; done
Expected Behavior
All 50 tests pass without workerd crash. Isolate teardown should handle deferred destruction gracefully when the isolate is shutting down.
Current Workaround
dangerouslyIgnoreUnhandledErrors: true in vitest config. The crash doesn't affect test correctness, just reporting.
Suggested Fix Direction
In src/workerd/jsg/setup.c++:235, the KJ_REQUIRE assertion in deferDestruction() crashes when queueState == DROPPING. For ephemeral Worker Loader isolates, this could either:
- Silently drop the deferred item (the isolate is being destroyed anyway)
- Drain the deferred queue before transitioning to
DROPPING state
Environment
["nodejs_compat"]Describe the Bug
When running vitest tests that use
worker_loadersbinding to create many ephemeral isolates (40+ per test file vialoader.load()), workerd intermittently crashes during isolate teardown with:This appears to be a race condition where a JS callback in the ephemeral isolate tries to call
deferDestruction()after the isolate has already entered theDROPPING(1) state in itsdropWrappers()shutdown phase.The crash is probabilistic — roughly 1 in 5 runs in our test suite. It does not affect test correctness (all assertions pass before the crash), but it causes workerd to exit unexpectedly, sometimes preventing vitest from collecting the last few test results.
Minimal Reproduction
wrangler.test.jsonc:{ "name": "repro", "main": "src/index.ts", "compatibility_date": "2025-01-13", "compatibility_flags": ["nodejs_compat"], "worker_loaders": [{ "binding": "LOADER" }] }vitest.workers.config.ts:src/repro.test.ts:Run 5 times — at least 1 will crash:
Expected Behavior
All 50 tests pass without workerd crash. Isolate teardown should handle deferred destruction gracefully when the isolate is shutting down.
Current Workaround
dangerouslyIgnoreUnhandledErrors: truein vitest config. The crash doesn't affect test correctness, just reporting.Suggested Fix Direction
In
src/workerd/jsg/setup.c++:235, theKJ_REQUIREassertion indeferDestruction()crashes whenqueueState == DROPPING. For ephemeral Worker Loader isolates, this could either:DROPPINGstate