vitejs/vite · error · Error
fetchModule is disabled in this environment
Error message
fetchModule is disabled in this environment
What it means
The hot channel's invoke handler for fetchModule at packages/vite/src/node/server/environment.ts:161 throws when context.disableFetchModule is true. Environments that opt out of module fetching over the hot channel (e.g. remote runner transports, some bundled-dev setups) set this flag; any caller that still issues a fetchModule invoke gets rejected.
Source
Thrown at packages/vite/src/node/server/environment.ts:161
this._crawlEndFinder = setupOnCrawlEnd()
this._remoteRunnerOptions = context.remoteRunner ?? {}
this._skipFsCheck = !!(
context.transport &&
!(isWebSocketServer in context.transport) &&
context.transport.skipFsCheck
)
this.hot = context.transport
? isWebSocketServer in context.transport
? context.transport
: normalizeHotChannel(context.transport, context.hot)
: normalizeHotChannel({}, context.hot)
this.hot.setInvokeHandler({
fetchModule: (id, importer, options) => {
if (context.disableFetchModule) {
throw new Error('fetchModule is disabled in this environment')
}
return this.fetchModule(id, importer, options)
},
getBuiltins: async () => {
return this.config.resolve.builtins.map((builtin) =>
typeof builtin === 'string'
? { type: 'string', value: builtin }
: { type: 'RegExp', source: builtin.source, flags: builtin.flags },
)
},
})
this.hot.on(
'vite:invalidate',
({ path, message, firstInvalidatedBy }, client) => {
this.invalidateModule(
{
path,View on GitHub (pinned to 89620f09af)
Solutions
- Do not call fetchModule on environments where it is disabled — fetch modules through the path the environment intends (e.g. its remoteRunner or transport).
- When constructing the environment, leave disableFetchModule unset (default) if you need module fetching.
- Guard callers with environment.runner / transport feature detection before issuing fetchModule.
Example fix
// before
await environment.hot.invoke('fetchModule', id)
// after
if (!context.disableFetchModule) {
await environment.hot.invoke('fetchModule', id)
} else {
// use the environment's native module loader
} Defensive patterns
Strategy: type-guard
Validate before calling
function canFetchModule(ctx: { disableFetchModule?: boolean }): boolean {
return !ctx.disableFetchModule
}
if (canFetchModule(envContext)) {
await environment.hot.invoke('fetchModule', id, importer)
} Type guard
function fetchModuleEnabled(env: { hot: { invoke: (m: string) => unknown } } & { disableFetchModule?: boolean }): boolean {
return !(env as any).disableFetchModule
} Try / catch
try {
await env.hot.invoke('fetchModule', id)
} catch (e) {
if (/fetchModule is disabled/.test((e as Error).message)) {
// load the module through the environment's native runner instead
} else throw e
} Prevention
- Do not call fetchModule on remote/bundled environments that disable it.
- Feature-detect the environment's transport/runner before issuing fetchModule.
- Document per environment whether module fetching is supported.
When it happens
Trigger: Calling environment.hot.send / invoke('fetchModule', ...) (directly or via server.transport) on an environment whose context.disableFetchModule = true; a plugin or framework runtime that always calls fetchModule without checking support; mismatched server/client expectations where the client expects to fetch modules but the environment disabled it.
Common situations: Custom/remote environments that resolve modules themselves; bundled-dev mode where deps optimizer is disabled; frameworks (RSC, SSR runners) that ship their own module loading and turn fetchModule off.
Related errors
- currently full bundle mode is only available for client envi
- client ID conflict detected. Please restart the dev server.
- Environment "${name}" is not defined in the config.
- Invalid environment name "${name}". Environment names must o
- No environment found
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/621e03027622ea77.json.
Report an issue: GitHub.