vitest-dev/vitest · error · Error
[vitest] "register" is not available when running in Vitest.
Error message
[vitest] "register" is not available when running in Vitest.
What it means
Thrown by the stub `Module.register` static method on the fake CommonJS Module class used inside Vitest's vm executor (commonjs-executor.ts). Node's real `module.register()` registers an ESM loader hook chain; Vitest provides its own module system inside workers, so that API is intentionally disabled and surfaces this explicit error rather than silently doing nothing.
Solutions
- Avoid calling `module.register` in code that runs under Vitest; gate it behind an environment check (e.g. only register when not in a Vitest worker).
- Use Vitest's own loader/server.mode or `server.deps.inline` mechanisms instead of a self-registering loader.
- Mock or stub the module that calls `register` in your test setup if its loader behavior is not under test.
- If the registration is essential, run that code in a child process spawned from the test rather than inside the Vitest module system.
Example fix
// before
import Module from 'node:module'
Module.register('./my-loader.mjs')
// after — skip registration under Vitest
import Module from 'node:module'
if (!process.env.VITEST) {
Module.register('./my-loader.mjs')
} Defensive patterns
Strategy: validation
Validate before calling
// Skip module.register when running under Vitest
const isVitest = !!process.env.VITEST
if (!isVitest) {
await import('node:module').then(m => m.register('./loader.mjs'))
} Type guard
function shouldSkipModuleRegister(): boolean {
return !!process.env.VITEST
} Try / catch
try {
Module.register('./loader.mjs')
} catch (e) {
if (String(e?.message).includes('"register" is not available when running in Vitest')) {
// expected under Vitest; fall through
} else throw e
} Prevention
- Gate Node loader-API calls behind a `!process.env.VITEST` check in libraries you test.
- Prefer Vitest-native extension points over self-registering loaders.
- Mock modules that register loaders when their hook behavior is not under test.
When it happens
Trigger: Code under test (loaded via Vitest's vm/commonjs executor) calls `module.register(...)` or `Module.register(...)` — e.g. a library that self-registers a custom ESM loader, or application code calling the module register API at import time.
Common situations: Testing a package that uses `module.register` to hook imports (e.g. for instrumentation, tracing, or tsx-style loading); running such code under Vitest's default forks/threads pools which use the vm-based CommonJS executor.
Related errors
- [vitest] "registerHooks" is not available when running in…
- Cannot import " ": its vm context was torn down.
- Cannot import " ": the test context was torn down.
- Environment " " is not a valid environment. Path " "…
- Environment doesn't provide a valid context. It should be…
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/766a0eadceaacc56.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vitest/src/runtime/vm/commonjs-executor.ts:134
}
const _require = Module.createRequire(this.id)
requiresCache.set(this, _require)
return _require
}
static getSourceMapsSupport = () => ({
enabled: false,
nodeModules: false,
generatedCode: false,
})
static setSourceMapsSupport = () => {
// noop
}
static register = () => {
throw new Error(
`[vitest] "register" is not available when running in Vitest.`,
)
}
static registerHooks = () => {
throw new Error(
`[vitest] "registerHooks" is not available when running in Vitest.`,
)
}
_compile(code: string, filename: string) {
const cjsModule = Module.wrap(code)
const codeCache = executor.codeCache
let script = cjsScriptCache.get(filename)
if (!script) {
const cachedData = codeCache?.get(filename, cjsModule)
// the dynamic import callback is a static function (the executor is
// resolved when it is called), so the compiled script holds noView on GitHub (pinned to 1fa9837ec2)