vitejs/vite · error · Error
Vite module runner has been closed.
Error message
Vite module runner has been closed.
What it means
`getModuleInformation` is the entry to module fetching; it first checks the runner's `closed` flag and throws if `close()` was called. After close, the runner's caches are cleared and the transport is disconnected, so no further imports are valid.
Solutions
- Guard imports with `runner.isClosed()` before calling `import`.
- Ensure no concurrent work references the runner after `close()`; await all in-flight imports before closing.
- Create a fresh runner if you need to import again after closing.
Example fix
// before
await runner.close()
await runner.import('/src/app.ts') // throws
// after
if (!runner.isClosed()) {
await runner.import('/src/app.ts')
} Defensive patterns
Strategy: try-catch
Validate before calling
async function safeImport(runner: { isClosed: () => boolean; import: (u: string) => Promise<unknown> }, url: string) {
if (runner.isClosed()) throw new Error(`Refusing to import ${url}: runner is closed`)
return runner.import(url)
} Type guard
function runnerIsAlive(runner: { isClosed: () => boolean }): boolean {
return !runner.isClosed()
} Try / catch
try {
return await runner.import(url)
} catch (e) {
if (e instanceof Error && /module runner has been closed/.test(e.message)) {
// re-create runner or skip - do not retry on the closed instance
return null
}
throw e
} Prevention
- Await all in-flight imports before calling runner.close().
- Gate further imports behind runner.isClosed() in long-lived services.
When it happens
Trigger: Calling `runner.import(url)` (or any operation that triggers `cachedModule`/`getModuleInformation`) after `await runner.close()` has resolved.
Common situations: Teardown races in tests where a module import is in-flight or queued after the runner is closed. Shared runner instances being closed by one consumer while another still imports. Long-running servers that close the runner during shutdown but still service requests.
Related errors
- invoke was called before connect
- [module runner] HMR client was closed.
- send was called before connect
- Cannot call server.listen in middleware mode.
- Cannot print server URLs before server is listening.
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/f15a9abd2cfe6424.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/module-runner/runner.ts:273
builtin,
)
this.isBuiltin = createIsBuiltin(builtins)
this.debug?.('[module runner] builtins loaded:', builtins)
} finally {
this.builtinsPromise = undefined
}
})()
return this.builtinsPromise
}
private async getModuleInformation(
url: string,
importer: string | undefined,
cachedModule: EvaluatedModuleNode | undefined,
): Promise<EvaluatedModuleNode> {
if (this.closed) {
throw new Error(`Vite module runner has been closed.`)
}
await this.ensureBuiltins()
this.debug?.('[module runner] fetching', url)
const isCached = !!(typeof cachedModule === 'object' && cachedModule.meta)
const fetchedModule = // fast return for established externalized pattern
(
url.startsWith('data:') || this.isBuiltin?.(url)
? { externalize: url, type: 'builtin' }
: await this.transport.invoke('fetchModule', [
url,
importer,
{
cached: isCached,
startOffset: this.evaluator.startOffset,View on GitHub (pinned to b4d66fee14)