Skip to content
Latchkey

Vitest "pool" Threads vs Forks - Worker Crashes & Native Module Errors

Vitest runs tests in a worker pool that defaults to threads (worker_threads). Native addons and code that mutates process-global state can crash or misbehave under threads; switching the pool to forks (child processes) isolates them.

What this error means

A suite crashes with "Module did not self-register," a segfault, or "Terminating worker thread" - only in Vitest, not when the same code runs under Node directly. It often appears after adding a native dependency or under the default thread pool.

Vitest output
Error: Module did not self-register: '.../node_modules/better-sqlite3/build/Release/better_sqlite3.node'

  ❯ Worker terminated due to reaching memory limit or native crash
  (pool: 'threads')

Common causes

Native addon loaded in a worker thread

A native N-API addon (better-sqlite3, canvas, bcrypt) may not support being loaded into multiple worker threads, and self-registration fails or crashes under the threads pool.

Process-global state shared across threads

Code that relies on per-process globals (some singletons, certain mocks) behaves incorrectly when many threads share one process. Forks give each test file its own process.

How to fix it

Switch the pool to forks

Run each test file in a child process instead of a worker thread.

vitest.config.ts
// vitest.config.ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
  test: { pool: 'forks', poolOptions: { forks: { singleFork: false } } },
});

Tune isolation and concurrency

  1. Use poolOptions.forks.singleFork: true for code that must share one process.
  2. Cap maxForks/minForks (or maxThreads) to control memory on big runners.
  3. Keep threads for pure-JS suites where it is faster; only move offending files to forks.

How to prevent it

  • Use the forks pool for suites that load native addons.
  • Pin pool options in config so CI and local match.
  • Avoid process-global singletons in code under test.

Frequently asked questions

What causes "Vitest pool crash"?
A native N-API addon (better-sqlite3, canvas, bcrypt) may not support being loaded into multiple worker threads, and self-registration fails or crashes under the threads pool.
How do I fix Vitest pool crash?
Run each test file in a child process instead of a worker thread.

Related guides

References

Latchkey auto-heals failures like this one - detected, fixed, and retried without you. Start free → 30-day trial · No credit card