vitejs/vite · error · Error
HMR is not supported by this runner transport, but `hmr`…
Error message
HMR is not supported by this runner transport, but `hmr` option was set to true
What it means
When constructing a ModuleRunner with `hmr` not false, the constructor checks that `transport.connect` exists - HMR requires a duplex transport that can receive push messages. If the transport only supports invoke (request/response) and has no `connect`, the constructor throws immediately because HMR cannot function.
Solutions
- Set `hmr: false` in the ModuleRunner options if you do not need hot updates.
- Implement `connect` on your transport (a method that registers a handler and returns a disposer) to enable HMR.
Example fix
// before
new ModuleRunner({ transport: { invoke: fetchModule /* no connect */ } })
// after
new ModuleRunner({ transport: { invoke: fetchModule }, hmr: false }) Defensive patterns
Strategy: validation
Validate before calling
function validateRunnerTransportForHmr(transport: { connect?: unknown }, hmr: unknown) {
if (hmr !== false && typeof transport.connect !== 'function') {
throw new Error('Transport has no connect() - set hmr: false or implement connect')
}
} Type guard
function transportSupportsHmr(t: unknown): t is { connect: () => void; invoke: (...a: any[]) => any } {
return !!t && typeof (t as any).connect === 'function' && typeof (t as any).invoke === 'function'
} Prevention
- If your transport is fetch-only (invoke only), always set hmr: false on the runner.
- When implementing HMR, implement connect(handler): disposer on the transport.
When it happens
Trigger: Constructing `new ModuleRunner({ transport: invokeOnlyTransport, hmr: true })` (or leaving `hmr` at its default `true`) where `transport.connect` is undefined. Common when reusing a fetch-only transport (e.g. a manual `fetchModule` wrapper) for SSR evaluation that does not implement HMR.
Common situations: Building a custom module-runner transport for SSR/testing that omits `connect`. Forgetting to disable HMR in a one-shot evaluation script.
Related errors
- Cannot send non-custom events from the client to the server.
- Cannot send non-custom events from the server to the client.
- client ID conflict detected. Please restart the dev server.
- invoke was called before connect
- [module runner] Failed to load
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/f02d1375e245935b.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/module-runner/runner.ts:74
private debug?: ModuleRunnerDebugger | undefined,
) {
this.evaluatedModules = options.evaluatedModules ?? new EvaluatedModules()
this.transport = normalizeModuleRunnerTransport(options.transport)
if (options.hmr !== false) {
const optionsHmr = options.hmr ?? true
const resolvedHmrLogger: HMRLogger =
optionsHmr === true || optionsHmr.logger === undefined
? hmrLogger
: optionsHmr.logger === false
? silentConsole
: optionsHmr.logger
this.hmrClient = new HMRClient(
resolvedHmrLogger,
this.transport,
({ acceptedPath }) => this.import(acceptedPath),
)
if (!this.transport.connect) {
throw new Error(
'HMR is not supported by this runner transport, but `hmr` option was set to true',
)
}
this.transport.connect(createHMRHandlerForRunner(this))
} else {
this.transport.connect?.()
}
if (options.sourcemapInterceptor !== false) {
this.resetSourceMapSupport = enableSourceMapSupport(this)
}
}
/**
* URL to execute. Accepts file path, server path or id relative to the root.
*/
public async import<T = any>(url: string): Promise<T> {
const fetchedModule = await this.cachedModule(url)
return await this.cachedRequest(url, fetchedModule)View on GitHub (pinned to b4d66fee14)