vitest-dev/vitest · error · Error

process.nextTick cannot be mocked inside child_process

Error message

process.nextTick cannot be mocked inside child_process

What it means

`process.nextTick` cannot be safely faked inside a Node `child_process` (the `forks` pool runs each test file in a forked process where `process.send` exists). Mocking `nextTick` there breaks the IPC channel that keeps the worker alive and communicating with the main process. Vitest's `FakeTimers.useFakeTimers()` rejects an explicit `toFake` containing `'nextTick'` when `isChildProcess()` is true.

Source

Thrown at packages/vitest/src/integrations/mock/timers.ts:161

      this._clock.uninstall()
      this._fakingTime = false
    }
  }

  useFakeTimers(): void {
    const fakeDate = this._fakingDate || Date.now()
    if (this._fakingDate) {
      this._clock.uninstall()
      this._fakingDate = null
    }

    if (this._fakingTime) {
      this._clock.uninstall()
    }

    let toFake = this._userConfig?.toFake
    if (isChildProcess() && toFake?.includes('nextTick')) {
      throw new Error(
        'process.nextTick cannot be mocked inside child_process',
      )
    }

    let toNotFake = this._userConfig?.toNotFake
    if (toFake === undefined && toNotFake === undefined) {
      // Do not mock timers internally used by node by default. It can still be mocked through userConfig.
      toFake = (Object.keys(this._fakeTimers.timers) as FakeMethod[])
        .filter(timer => timer !== 'nextTick' && timer !== 'queueMicrotask')
    }
    if (isChildProcess() && toNotFake && !toNotFake.includes('nextTick')) {
      toNotFake = [...toNotFake, 'nextTick']
    }

    this._clock = this._fakeTimers.install({
      now: fakeDate,
      ...this._userConfig,
      ...(toFake && { toFake }),

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Switch the pool to `threads` (`--pool=threads` or `pool: 'threads'`) so nextTick mocking is supported.
  2. Remove `'nextTick'` from `toFake` and rely on the default, which already excludes `nextTick` and `queueMicrotask`.
  3. If you must fake nextTick and stay on forks, that combination is unsupported — restructure the test to avoid nextTick.

Example fix

// before (forks pool)
vi.useFakeTimers({ toFake: ['setTimeout', 'nextTick'] })
// after (run with --pool=threads)
// vitest.config.ts
export default defineConfig({ test: { pool: 'threads' } })
vi.useFakeTimers({ toFake: ['setTimeout', 'nextTick'] })
Defensive patterns

Strategy: validation

Validate before calling

// before enabling nextTick faking, confirm we are NOT in a child process
const isChild = typeof process !== 'undefined' && !!process.send
if (isChild && (config?.toFake ?? []).includes('nextTick')) {
  throw new Error('nextTick cannot be faked in forks/child_process; use --pool=threads')
}

Type guard

function canFakeNextTick(toFake: string[] = []): boolean {
  const isChild = typeof process !== 'undefined' && !!process.send
  return !(isChild && toFake.includes('nextTick'))
}

Prevention

When it happens

Trigger: Calling `vi.useFakeTimers({ toFake: ['nextTick', ...] })` (or passing `fakeTimers.toFake` containing `'nextTick'` via config) while running under the `forks` pool, which sets `process.send`.

Common situations: Setting `pool: 'forks'` (or relying on it as default in some setups) and globally enabling `fakeTimers.toFake: ['nextTick']`, or copying a timers config that worked under the `threads` pool into a forks run.

Related errors


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