cloudflare / cloudflare/workers-sdk
@cloudflare/vitest-pool-workers segfaults with 3+ real auxiliary Workers wired together (version-independent, minimal synthetic repro does not reproduce)
- Dominant language
- TypeScript
- Stars
- 4.5k
- Forks
- 1.5k
- Avg merge
- 3d 8h
- Merged PRs (30d)
- 186
Description
### Which Cloudflare product(s) does this pertain to?
Workers - Wrangler, Vitest-based testing tools
### What version(s) of the tool(s) are you using?
- `@cloudflare/vitest-pool-workers`: 0.18.8 AND 0.19.1 (latest at time of filing) — same crash, same signature on both
- `miniflare`: 4.20260722.0 (bundled by 0.18.8) AND 4.20260730.0 (bundled by 0.19.1)
- `workerd`: 1.20260722.1 AND 1.20260730.1
- `wrangler`: 4.100.0 (also reproduced against 4.114.0)
- `vitest`: 4.1.8
- Node: v26.4.0
- OS: macOS 15 (Darwin 25.5.0), Apple Silicon (arm64)
### What steps can we follow to reproduce this issue?
We have a multi-Worker integration test: one primary Worker plus three real auxiliary Workers, each wired via `serviceBindings`, each loaded through `wrangler.unstable_getMiniflareWorkerOptions()` against its own real, already-deployed `wrangler.jsonc` (so bindings — Hyperdrive, KV, Durable Objects, further nested `services` — are real, not invented for the test). All four are real production Cloudflare Workers, individually well-exercised in this pool for years; this is the first time all four run together in one pool instance.
The moment all three auxiliary Workers are wired together alongside the primary, `vitest run --project ` crashes with a raw `Segmentation fault: 11` before any test executes — no JS error, no stack trace, just the process dying.
**Isolation performed (all confirmed live, not assumed):**
- Any TWO of the three auxiliary Workers together (including a circular service-binding pair between two of them) start clean and pass tests.
- Only the full four-Worker graph (primary + all 3 real auxiliaries) crashes.
- NOT about Hyperdrive — crash persists with every `hyperdrives` binding stripped from all four Workers.
- NOT about Durable Objects — crash persists with every `durableObjects` binding stripped too.
- Purely "primary + 3 real named auxiliary Workers through this pool," independent of binding complexity we've tested.
- NOT fixed by upgrading `@cloudflare/vitest-pool-workers` 0.18.8 → 0.19.1 (`miniflare` 4.20260722.0 → 4.20260730.0) — identical crash, identical signature.
**What does NOT reproduce it:** a minimal synthetic reproduction — a trivial primary Worker plus up to 4 trivial auxiliary Workers (each just `export default { fetch() { return new Response(...) } }`), wired with real `serviceBindings` between them, same installed `0.18.8` — starts and serves requests cleanly every time, at every auxiliary count from 1 to 4. So this isn't simply "N auxiliary workers crashes the pool" — something about our real Workers' actual module graphs (larger bundles, `nodejs_compat`, dynamic imports, more binding types, or some combination) is a necessary ingredient we haven't isolated further. Happy to help narrow this down further with guidance on what to try next, or to share a redacted/synthetic repro repo if useful — we didn't want to hold off filing until we had a fully minimal case, since the signature (unconditional segfault, version-independent) seemed worth flagging as-is.
**Confirmed working as a control:** the identical four-Worker configuration (same real bindings, same real service-binding wiring, same Hyperdrive-backed Postgres), constructed with the `miniflare` package directly — bypassing `@cloudflare/vitest-pool-workers` entirely — starts cleanly and correctly proxies a request end-to-end through all four Workers. This rules out the Worker configs themselves, or `workerd`/`miniflare` in general, as the cause — it's specific to something in the pool's own wrapping (its runner worker, the Vite module-transform layer it puts in front of the primary Worker, and/or its inspector/WebSocket control channel).
### What is the actual behavior?
```
*** Received signal #11: Segmentation fault: 11
⎯⎯⎯⎯⎯⎯ Unhandled Errors ⎯⎯⎯⎯⎯⎯
Error: [vitest-pool]: Worker cloudflare-pool emitted error.
❯ EventEmitter. .../vitest/dist/chunks/cli-api.*.js
...
Caused by: Error: Worker exited unexpectedly
❯ _WebSocket.emitUnexpectedExit .../vitest/dist/chunks/cli-api.*.js
...
Test Files (1)
Tests no tests
Errors 1 error
```
No test in the file runs — the pool worker process dies during startup/wiring, before any test body executes.
### What is the expected behavior?
Either the pool starts successfully with a real 4-Worker graph (primary + 3 real auxiliary Workers with real bindings), matching the behavior of a raw `Miniflare` instance given the identical configuration — or, if there's a documented/known limit on auxiliary Worker count or complexity for this pool, a clear error message rather than a segfault.
### Additional information
We ended up moving this specific test off `@cloudflare/vitest-pool-workers` onto a raw `Miniflare` instance driven from a plain `node`-pool vitest project (same real bindings, same real service-binding wiring, same runtime) as a working alternative — filing this for visibility/tracking, not because we're blocked, and happy to help debug further if that's useful.
Contributor guide
Research direction
The failure occurs before tests in `vitest run --project `, while the same four-Worker setup works with raw Miniflare. Start by comparing `@cloudflare/vitest-pool-workers`' runner worker, Vite module-transform layer, and inspector/WebSocket control channel against the direct Miniflare path. Done means the graph starts without a segfault and a test executes, or a clear error is reported.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, node.js, typescript
- Domain
- testing, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100