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
- 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`).
- Restart the dev server / runner to reset inconsistent module state.
- 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
- Custom transports must honor the `cached` flag passed to fetchModule and only return { cache: true } when warranted.
- Keep vite updated - invalidation bugs are patched frequently.
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
- Cannot send non-custom events from the client to the server.
- Cannot send non-custom events from the server to the client.
- [module runner] Failed to load
- HMR is not supported by this runner transport, but `hmr`…
- invoke was called before connect
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 = moduleUrlView on GitHub (pinned to b4d66fee14)