vitest-dev/vitest · critical · Error

Expected worker to be run in node:child_process

Error message

Expected worker to be run in node:child_process

What it means

Module-level guard in init-forks.ts (line 5-7): the forks worker entrypoint requires process.send to exist, which is only present when the process is spawned as a node:child_process fork. If the file is imported in any other context it throws immediately at import time.

Source

Thrown at packages/vitest/src/runtime/workers/init-forks.ts:6

import type { WorkerGlobalState, WorkerSetupContext } from '../../types/worker'
import type { Traces } from '../../utils/traces'
import { init } from './init'

if (!process.send) {
  throw new Error('Expected worker to be run in node:child_process')
}

// Store globals in case tests overwrite them
const processExit = process.exit.bind(process)
const processSend = process.send.bind(process)
const processOn = process.on.bind(process)
const processOff = process.off.bind(process)
const processRemoveAllListeners = process.removeAllListeners.bind(process)

const isProfiling = process.execArgv.some(
  execArg =>
    execArg.startsWith('--prof')
    || execArg.startsWith('--cpu-prof')
    || execArg.startsWith('--heap-prof')
    || execArg.startsWith('--diagnostic-dir'),
)

// Work-around for nodejs/node#55094

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Do not import init-forks directly; let Vitest spawn the fork via pool: 'forks'.
  2. If building a custom pool that uses child_process.fork, ensure the entry is only loaded inside the forked process.
  3. Switch the pool to 'threads' if you actually want worker_threads.

Example fix

// before: importing the forks entry in the main process
import './node_modules/vitest/dist/workers/forks.js'

// after: let vitest fork it via config
// vitest.config.ts
export default defineConfig({ test: { pool: 'forks' } })
Defensive patterns

Strategy: validation

Validate before calling

import { isMainThread } from 'node:worker_threads'

function assertForkContext() {
  const isForkedChild = typeof process.send === 'function'
  if (!isForkedChild && isMainThread) {
    throw new Error(
      'init-forks must be loaded inside a child_process.fork; do not import it from the main process.'
    )
  }
}

Prevention

When it happens

Trigger: Importing packages/vitest .../workers/init-forks.ts (or the built runForksTests entry) directly from the main process, a worker thread, or a normal script — anywhere process.send is undefined. Vitest itself only loads this file inside a forked child of the forks pool.

Common situations: A custom pool or test that imports the forks worker module to reuse its logic; a misconfigured pool that points at the forks entry but spawns a worker_thread instead of a fork; importing internal vitest paths for experimentation.

Related errors


AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03). Data as JSON: /data/errors/6ede1e97c5d28599.json. Report an issue: GitHub.