vitejs/vite · error · Error

HMR is not supported by this runner transport, but `hmr` opt

Error message

HMR is not supported by this runner transport, but `hmr` option was set to true

What it means

Thrown in the ModuleRunner constructor when options.hmr is not false (defaults to true) but the provided transport has no connect method. HMR requires a persistent connection to receive push notifications from the server, so the transport must implement connect(). If the transport only implements invoke (request-response pattern) without connect, HMR cannot function and the constructor fails immediately.

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 89620f09af)

Solutions

  1. Set hmr: false when creating the runner if your transport doesn't support connect: new ModuleRunner({ transport, hmr: false }).
  2. Implement a connect method on your transport (even a no-op if you handle messaging through invoke) if you need HMR.
  3. Use createWebSocketModuleRunnerTransport from Vite which provides a complete connect/disconnect/send implementation over WebSocket.

Example fix

// before — custom transport without connect, HMR enabled by default
const runner = new ModuleRunner({
  transport: { invoke: myInvokeFn } // no connect
})
// after — explicitly disable HMR
const runner = new ModuleRunner({
  transport: { invoke: myInvokeFn },
  hmr: false
})
Defensive patterns

Strategy: validation

Validate before calling

// Validate transport supports HMR before creating the runner
function validateTransportForHmr(transport, hmrOption) {
  if (hmrOption !== false && !transport.connect) {
    throw new Error('Transport must implement connect() to support HMR. Set hmr: false to disable.')
  }
}

// Or auto-resolve
const hmr = transport.connect ? (options.hmr ?? true) : false
const runner = new ModuleRunner({ transport, hmr })

Type guard

function transportSupportsHmr(transport: ModuleRunnerTransport): boolean {
  return typeof transport.connect === 'function'
}

Prevention

When it happens

Trigger: Creating a ModuleRunner with a custom transport that only implements invoke (or send) but not connect, while leaving hmr at its default (true) or explicitly setting hmr: true. Common when building a custom transport for request-response-only module loading (e.g., HTTP-based fetch without WebSocket).

Common situations: Using a custom ManuallyTriggeredTransport or HTTP-based transport that doesn't maintain a persistent connection. Integrating Vite's module runner in a non-standard runtime (e.g., serverless, edge) where WebSocket connections aren't available. Copying a transport implementation that omits connect.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/f02d1375e245935b.json. Report an issue: GitHub.