vitest-dev/vitest · error · Error
Cannot import "${mod.identifier}": its vm context was torn d
Error message
Cannot import "${mod.identifier}": its vm context was torn down. What it means
Thrown by getContextExecutor when a module's vm context no longer carries the VITEST_VM_CONTEXT_SYMBOL property, meaning the context was disposed (torn down) while a dynamic import or import.meta.resolve is still being serviced against a module that lived in it. Vitest associates each test file's vm world with a context; once that file's run ends the context is torn down and any lingering reference fails fast.
Source
Thrown at packages/vitest/src/runtime/vm/esm-executor.ts:67
}
return { mime, code: Buffer.from(code, 'base64') }
}
if (!encoding || encoding === 'charset=utf-8') {
code = decodeURIComponent(code)
}
else if (encoding === 'base64') {
code = Buffer.from(code, 'base64').toString()
}
else {
throw new Error(`Invalid data URI encoding: ${encoding}`)
}
return { mime, code }
}
function getContextExecutor(mod: VMModule): ExternalModulesExecutor {
const vmContext = (mod.context as any)?.[VITEST_VM_CONTEXT_SYMBOL]
if (!vmContext) {
throw new Error(`Cannot import "${mod.identifier}": its vm context was torn down.`)
}
return vmContext.externalModulesExecutor
}
async function staticImportModuleDynamically(specifier: string, referencer: VMModule): Promise<VMModule> {
return getContextExecutor(referencer).importModuleDynamically(specifier, referencer)
}
function staticInitializeImportMeta(meta: ImportMeta, mod: VMModule): void {
meta.url = mod.identifier
if (mod.identifier.startsWith('file:')) {
const filename = fileURLToPath(mod.identifier)
meta.filename = filename
meta.dirname = dirname(filename)
}
meta.resolve = (specifier: string, importer?: string | URL) => {
return getContextExecutor(mod).resolve(
specifier,View on GitHub (pinned to 1fa9837ec2)
Solutions
- Ensure async work that performs dynamic imports completes (or is cancelled) before the test file finishes — await it in the test or clean it up in afterAll.
- Avoid caching modules or contexts across file boundaries; let each file's vm world be self-contained.
- If using workers/subprocesses, terminate them in teardown so they cannot issue imports afterward.
- Treat this as a symptom of a lifecycle leak: find what holds the module reference past teardown.
Example fix
// before — dynamic import resolves after teardown
let mod
beforeAll(() => {
setTimeout(() => { mod = await import('./late') }, 10000)
})
// after — await inside the test lifecycle
beforeAll(async () => {
mod = await import('./late')
}) Defensive patterns
Strategy: validation
Validate before calling
// Ensure async work that imports modules completes before file teardown
import { beforeEach, afterEach } from 'vitest'
let pending: Promise<unknown> | null = null
beforeEach(() => { pending = null })
afterEach(async () => { if (pending) await pending })
function track(p: Promise<unknown>) { pending = p } Try / catch
try {
await import(/* @vite-ignore */ specifier)
} catch (e) {
if (String(e?.message).includes('its vm context was torn down')) {
// the originating file's vm world is gone; abandon the import
return
}
throw e
} Prevention
- Await all dynamic imports inside the test/beforeAll/afterAll that owns them.
- Cancel timers, workers, and fetches in teardown so they cannot import later.
- Do not share module references across files; keep each file's vm world self-contained.
- Treat this error as a lifecycle-leak signal and fix the leak, not the symptom.
When it happens
Trigger: An asynchronous import() or `import.meta.resolve` triggered by a module in a finished test file resolves after the file's vm context has been disposed — e.g. a pending dynamic import or worker callback that fires during/after teardown. Reached via staticImportModuleDynamically and staticInitializeImportMeta's meta.resolve.
Common situations: Long-running async work (timers, workers, fetch) started in one test file that tries to dynamically import code after the file's run completed; sharing a module reference across files in a way that outlives its vm context; race conditions during fast bail/cancel where contexts are torn down while imports are mid-flight.
Related errors
- Invalid data URI
- Cannot import "${specifier}": the test context was torn down
- Root project is not initialized. This means that the Vite se
- Missing data URI encoding
- Invalid data URI encoding: ${encoding}
AI-assisted analysis of vitest-dev/vitest@1fa9837ec2 (2026-08-11).
Data as JSON: /api/errors/430744304fd6b009.
Report an issue: GitHub.