vitejs/vite · error · Error

Module " " was mistakenly invalidated during fetch phase.

Error message

Module "${url}" was mistakenly invalidated during fetch phase.

What it means

When the transport returns a result with a `cache` flag (telling the runner to reuse its cached module), the runner validates that a cached module actually exists (`cachedModule?.meta`). If the server says 'use cache' but the runner has no cached entry, that indicates a state inconsistency - the server invalidated/cleared something it shouldn't have during the fetch phase - so the runner throws rather than return stale or missing data.

Solutions

  1. If you implemented a custom transport, only return `{ cache: true }` when the runner previously reported having the module (track via the `cached` option passed to `fetchModule`).
  2. Restart the dev server / runner to reset inconsistent module state.
  3. Update vite to the latest patch - this is often triggered by a fixed invalidation bug.

Example fix

// before (custom transport)
invoke('fetchModule', [url, importer, opts]) {
  return { cache: true } // claimed even on first fetch
}
// after
invoke('fetchModule', [url, importer, opts]) {
  if (opts.cached && hasInStore(url)) return { cache: true }
  return fetchFresh(url)
}
Defensive patterns

Strategy: validation

Validate before calling

// For custom transports: only return { cache: true } when the runner previously had the module
function buildFetchResult(url: string, opts: { cached: boolean }, store: Map<string, unknown>) {
  if (opts.cached && store.has(url)) return { cache: true }
  const code = store.get(url) as string // or fetch fresh
  return { code, url, id: url }
}

Try / catch

try {
  return await runner.import(url)
} catch (e) {
  if (e instanceof Error && /mistakenly invalidated during fetch phase/.test(e.message)) {
    // restart the runner / reset dev server module graph, then retry once
  } else throw e
}

Prevention

When it happens

Trigger: The module-runner server/transport responds with `{ cache: true }` for a module the runner never fetched (or whose `meta` was cleared). Usually a transport bug or incorrect invalidation during the fetch phase of the same request.

Common situations: Custom transports that eagerly return `cache` without tracking runner state. Race conditions where modules are invalidated mid-fetch. Bugs in dev server invalidation logic interacting with the runner.

Related errors


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

Appendix: source

Thrown at packages/vite/src/module-runner/runner.ts:298

    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,
              },
            ])
      ) as ResolvedResult

    if ('cache' in fetchedModule) {
      if (!cachedModule || !cachedModule.meta) {
        throw new Error(
          `Module "${url}" was mistakenly invalidated during fetch phase.`,
        )
      }
      return cachedModule
    }

    const moduleId =
      'externalize' in fetchedModule
        ? fetchedModule.externalize
        : fetchedModule.id
    const moduleUrl = 'url' in fetchedModule ? fetchedModule.url : url
    const module = this.evaluatedModules.ensureModule(moduleId, moduleUrl)

    if ('invalidate' in fetchedModule && fetchedModule.invalidate) {
      this.evaluatedModules.invalidateModule(module)
    }

    fetchedModule.url = moduleUrl

View on GitHub (pinned to b4d66fee14)