vitejs/vite · error · Error

invalid hot.accept() usage.

Error message

invalid hot.accept() usage.

What it means

Thrown by the HMR context's accept() when the deps argument is neither undefined/null, nor a function (self-accept), nor a string, nor an array. accept only supports those four shapes; anything else (an object, number, boolean) is a misuse of the HMR API.

Solutions

  1. Use one of the supported forms: hot.accept(), hot.accept(cb), hot.accept('./dep', cb), or hot.accept(['./a','./b'], cb).
  2. If accepting multiple deps, pass an array of strings, not an object.
  3. Check that any framework/plugin generating hot.accept() calls emits a valid argument shape.

Example fix

// before
import.meta.hot.accept({ './a': cb }) // throws
// after
import.meta.hot.accept(['./a'], cb)
Defensive patterns

Strategy: validation

Validate before calling

function isValidAcceptDeps(deps: unknown): boolean {
  return deps == null || typeof deps === 'function' || typeof deps === 'string' || Array.isArray(deps)
}

Type guard

function isValidAcceptArg(deps: unknown): boolean {
  return deps == null || typeof deps === 'function' || typeof deps === 'string' || Array.isArray(deps)
}

Prevention

When it happens

Trigger: Calling import.meta.hot.accept(deps) where deps is an object, number, or other invalid type. The final else branch at hmr.ts:74 fires after the function/string/array checks fail.

Common situations: Passing an object map of dependencies by mistake. Spreading into accept with a bad shape. Mis-typed HMR API surface in a framework wrapper around import.meta.hot. Generated HMR code from a misbehaving plugin.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/de3f53d34b6f67aa. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/shared/hmr.ts:74

    this.newListeners = new Map()
    hmrClient.ctxToListenersMap.set(ownerPath, this.newListeners)
  }

  get data(): any {
    return this.hmrClient.dataMap.get(this.ownerPath)
  }

  accept(deps?: any, callback?: any): void {
    if (typeof deps === 'function' || !deps) {
      // self-accept: hot.accept(() => {})
      this.acceptDeps([this.ownerPath], ([mod]) => deps?.(mod))
    } else if (typeof deps === 'string') {
      // explicit deps
      this.acceptDeps([deps], ([mod]) => callback?.(mod))
    } else if (Array.isArray(deps)) {
      this.acceptDeps(deps, callback)
    } else {
      throw new Error(`invalid hot.accept() usage.`)
    }
  }

  // export names (first arg) are irrelevant on the client side, they're
  // extracted in the server for propagation
  acceptExports(
    _: string | readonly string[],
    callback?: (data: any) => void,
  ): void {
    this.acceptDeps([this.ownerPath], ([mod]) => callback?.(mod))
  }

  dispose(cb: (data: any) => void): void {
    this.hmrClient.disposeMap.set(this.ownerPath, cb)
  }

  prune(cb: (data: any) => void): void {
    this.hmrClient.pruneMap.set(this.ownerPath, cb)

View on GitHub (pinned to b4d66fee14)