vitest-dev / vitest-dev/vitest

threads pool worker isolate SIGSEGVs in V8 GC on large suites (vite 8 rolldown, node 24/26, macOS arm64)

Open
#11,291 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

pending triage
Dominant language
TypeScript
Stars
17.1k
Forks
2k
Avg merge
1d 22h
Merged PRs (30d)
94

Description

Describe the bug

Running a large test suite (454 files, ~4.9k tests) through the Node API with pool: 'threads' and maxWorkers: 1 reliably crashes the process with SIGSEGV during V8 GC on the threads-pool worker isolate. The same file set runs clean under pool: 'forks' (both via the CLI and via the Node API).

Reproduction

Against https://github.com/novus-power/hive (public), on a fresh clone with pnpm install:

// repro.mjs, run with `node repro.mjs` from the repo root
import { createVitest } from "vitest/node";
import fs from "node:fs";

process.env.NODE_ENV = "test";
process.env.VITEST = "1";

const report = JSON.parse(fs.readFileSync("related.json", "utf8")); // testResults[].name of the 454 related files, see below
const files = report.testResults.map((t) => t.name.replace(process.cwd() + "/", ""));

const ctx = await createVitest("test", {
  config: "vitest.config.ts",
  pool: "threads",
  maxWorkers: 1,
  coverage: { enabled: false },
  watch: false,
  bail: 1,
});
const specs = await ctx.globTestSpecifications(files);
await ctx.runTestSpecifications(specs);
await ctx.close();

related.json is just npx vitest related --run --reporter=json --outputFile=related.json core/graph/d1/src/*.ts (excluding test files) — the related set of that package's sources. We couldn't shrink it to a synthetic repro: a generated 420-file suite with real better-sqlite3 and PGlite usage per test does not crash; the real repo's module graph and test weight appear to be what pushes the worker isolate into the crashing GC window.

Expected behaviour

No SIGSEGV; or at worst the same behaviour forks pool exhibits (clean run).

Environment

  • Vitest 4.1.10, vite 8.1.4 (rolldown)
  • node 24.19.0 and node 26.8.1, both reproduce
  • macOS 15 arm64 (also seen on GitHub Actions arm64 macOS runners)

Additional context

Crash signature from macOS DiagnosticReports, consistent across every occurrence (~15 crash reports on this machine alone, since these runs are part of our CI): faulting thread is the pool's WorkerThread, stack terminates in either

  • v8::internal::Isolate::DeinitHeap::StartTearDownCppHeap::StartDetachingIsolateHeap::CollectGarbageGlobalHandles::InvokeFirstPassWeakCallbacks → SIGSEGV (worker teardown GC), or
  • IncrementalMarkingJob::Task::RunInternalMarkCompactCollector::StartMarkingMarkingWorklists::Local::~Local → SIGSEGV (near-null deref, 0x89).

The crashing process hosts 18 rolldown-worker native threads (vite 8 transforms) alongside the worker isolate; only .node addons loaded are rolldown-binding.darwin-arm64.node and fsevents.node. This is why we originally hit it through StrykerJS — its vitest runner forces pool: 'threads' (https://github.com/stryker-mutator/stryker-js/issues/6223) — but the repro above has no Stryker involved.

Happy to run instrumented builds or test candidate fixes against the repro if that helps.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running repro.mjs from the hive repository with the listed Node, Vitest, and Vite versions, using related.json and vitest.config.ts as described. Compare the threads-pool run through createVitest and runTestSpecifications with the clean forks-pool behavior, then investigate the reported worker-isolate teardown and incremental-marking crash paths. Done means the reproduced suite completes without SIGSEGV and matches the forks-pool result.

Written by the indexing model from the issue text.

Assessment

Tech stack
node.js, typescript
Domain
devtools, testing-qa
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.