vitest-dev/vitest · error · SyntaxError

require() is not supported in virtual modules. Trying to cal

Error message

require() is not supported in virtual modules. Trying to call require("${id}") in ${url}

What it means

`VitestModuleEvaluator.createRequire` (`moduleEvaluator.ts:436`) returns a throwing stub for modules whose URL begins with `data:` — these are virtual modules synthesized inline (e.g. automock/manual-generated source has no filesystem path). Node's `require` cannot resolve anything from a `data:` URL, so any `require()` call inside such a module throws this `SyntaxError` naming the required id and the calling url.

Source

Thrown at packages/vitest/src/runtime/moduleRunner/moduleEvaluator.ts:436

      await initModule(...argumentsValues)
    }
    catch (error: unknown) {
      if (!injectCjsGlobals) {
        throw enhanceMissingCjsGlobalsError(error)
      }
      throw error
    }
    finally {
      // moduleExecutionInfo needs to use Node filename instead of the normalized one
      // because we rely on this behaviour in coverage-v8, for example
      this.options.moduleExecutionInfo?.set(options.filename, finishModuleExecutionInfo())
    }
  }

  private createRequire(url: string) {
    if (url.startsWith('data:')) {
      const _require = (id: string) => {
        throw new SyntaxError(`require() is not supported in virtual modules. Trying to call require("${id}") in ${url}`)
      }
      _require.resolve = _require
      return _require
    }
    return this.vm
      ? this.vm.externalModulesExecutor.createRequire(url)
      : createRequire(url)
  }

  private shouldInterop(path: string, mod: any): boolean {
    if (this.options.interopDefault === false) {
      return false
    }
    // never interop ESM modules
    // TODO: should also skip for `.js` with `type="module"`
    return !path.endsWith('.mjs') && 'default' in mod
  }
}

View on GitHub (pinned to d568f8ce37)

Solutions

  1. Rewrite the module to use ESM `import` instead of `require`.
  2. If you control the mocked code, replace `require` with `createRequire`-free ESM imports or `import.meta`.
  3. Provide a manual mock factory (`vi.mock('mod', () => ({...}))`) that doesn't surface `require` to the evaluator.

Example fix

// before (module being mocked)
const fs = require('node:fs')

// after
import * as fs from 'node:fs'
Defensive patterns

Strategy: validation

Validate before calling

// Ensure mocked modules don't use require. Scan before mocking if you
// control the source; otherwise provide a manual factory.
function usesRequire(source: string): boolean {
  return /\brequire\s*\(/.test(source)
}

Try / catch

try {
  vi.mock('mod') // automock
} catch (e) {
  if (e instanceof SyntaxError && /require\(\) is not supported in virtual modules/.test(e.message)) {
    // provide a manual factory without require
    vi.mock('mod', () => ({ /* ... */ }))
  } else throw e
}

Prevention

When it happens

Trigger: An automocked or manually-mocked module (generated `data:` source) that contains a `require()` call; a virtual/Vite-synthesized module using `require`.

Common situations: Automocking a CJS-leaning module that calls `require('...')` internally; a manual mock factory whose generated wrapper references `require`; inlining a CJS dependency.

Related errors


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