vitejs/vite · critical · Error

Module "${url}" was mistakenly invalidated during fetch phas

Error message

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

What it means

Thrown in getModuleInformation when the server's fetchModule response includes a cache: true flag (indicating the module hasn't changed since last fetch) but the runner has no cached module for this URL (cachedModule is null or has no meta). This is a state inconsistency: the server assumes the client has the module cached, but the client's cache was cleared or never populated. It typically indicates a race condition between invalidation and fetching.

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

Solutions

  1. Avoid calling clearCache() while imports are in-flight; wait for all pending import() promises to settle first.
  2. If using HMR, let the HMR handler manage cache invalidation rather than calling clearCache() manually.
  3. Ensure your transport implementation correctly forwards the cache flag and doesn't falsely set it.
  4. In test environments, fully tear down the runner (await close()) before creating a new one rather than clearing mid-operation.

Example fix

// before — clearing cache during in-flight imports
runner.import('/src/a.ts') // in-flight
runner.clearCache()        // wipes cache
// the server may now respond with { cache: true } for a module
//   the runner no longer has -> throws
// after — await pending imports before clearing
await pendingImportPromise
runner.clearCache()
Defensive patterns

Strategy: validation

Validate before calling

// Prevent concurrent clearCache + import races
let importCount = 0
let clearPending = false

async function guardedImport(runner, url) {
  if (clearPending) throw new Error('Cache clear in progress')
  importCount++
  try {
    return await runner.import(url)
  } finally {
    importCount--
  }
}

async function guardedClearCache(runner) {
  if (importCount > 0) {
    console.warn('Waiting for in-flight imports before clearing cache')
    // use a promise that resolves when importCount reaches 0
  }
  clearPending = true
  runner.clearCache()
  clearPending = false
}

Try / catch

try {
  await runner.import(url)
} catch (e) {
  if (e.message.includes('mistakenly invalidated during fetch phase')) {
    console.error('Cache race detected. Avoid calling clearCache() during imports.')
    // may need to recreate the runner
  }
  throw e
}

Prevention

When it happens

Trigger: The runner's evaluatedModules cache is cleared (via clearCache()) while a concurrent fetch is in-flight. The server then responds with cache: true for a module the runner no longer has. Can also occur with custom transport implementations that incorrectly cache or replay fetch responses, or when multiple runner instances share a server that assumes state continuity.

Common situations: Calling clearCache() during HMR or SSR while async imports are pending. Race conditions in test environments where the runner is reset between tests but async operations from the previous test are still running. Custom transport middleware that incorrectly marks responses as cacheable.

Related errors


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