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#55094View on GitHub (pinned to d568f8ce37)
Solutions
- Do not import init-forks directly; let Vitest spawn the fork via pool: 'forks'.
- If building a custom pool that uses child_process.fork, ensure the entry is only loaded inside the forked process.
- 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
- Never import vitest internal worker entry files from application or test code.
- When building a custom pool, spawn the entry via child_process.fork and load it only there.
- Treat pool selection as a config-only concern (test.pool) rather than a code import.
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
- Expected worker to be run in node:worker_threads
- process.nextTick cannot be mocked inside child_process
- vi.useFakeTimers({ toFake: ["nextTick"] }) is not supported
- Expected string coverage payload, received ${typeof coverage
- Errors occurred while running tests. For more information, s
AI-assisted analysis of vitest-dev/vitest@d568f8ce37 (2026-08-03).
Data as JSON: /data/errors/6ede1e97c5d28599.json.
Report an issue: GitHub.