vitejs/vite · error · Error
[module runner] "import.meta.glob" is statically replaced…
Error message
[module runner] "import.meta.glob" is statically replaced during file transformation. Make sure to reference it by the full name.
What it means
`import.meta.glob` is not a real runtime function - Vite statically transforms it into an import map during file transformation. If the call survives to the module runner (i.e. the proxy/placeholder `glob()` throws), it means the transform did not replace it, almost always because the code references it indirectly (via a renamed alias, a variable, `window['import.meta.glob']`-style access, or code that the Vite plugin pipeline never processed).
Solutions
- Always call `import.meta.glob(...)` by its full name inline at the use site so Vite's transform can see and replace it.
- If you need a reusable helper, write a wrapper module that calls `import.meta.glob` and re-exports the result - do not pass the function itself around.
- Ensure the file is actually transformed by Vite (imported through the Vite module graph, not read via raw fs/Node).
Example fix
// before - aliased, transform cannot see it
const glob = import.meta.glob
const mods = glob('./pages/*.vue')
// after - inline full name
const mods = import.meta.glob('./pages/*.vue') Defensive patterns
Strategy: validation
Validate before calling
// Lint: flag aliasing/indirection of import.meta.glob in runner-executed code
function hasAliasedImportMetaGlob(src: string): boolean {
return /(?:const|let|var)\s+\w+\s*=\s*import\.meta\.glob\b/.test(src)
|| /import\.meta\.glob\b(?!\s*\()/.test(src)
} Try / catch
try {
import.meta.glob('./pages/*.vue')
} catch (e) {
if (e instanceof Error && /import.meta.glob.*statically replaced/.test(e.message)) {
// rewrite call site to use the full name inline
} else throw e
} Prevention
- Always write import.meta.glob(...) inline at the call site - never alias or pass it as a value.
- If you need a helper, wrap the result (the map), not the function itself.
When it happens
Trigger: Aliasing `import.meta.glob` to a short variable (`const g = import.meta.glob; g(...)`), passing it as a callback, string-looking it up, or executing code outside Vite's transform pipeline (raw Node import, a precompiled file not run through Vite). The throw fires from the default import meta's `glob()` stub.
Common situations: Refactors that extract `import.meta.glob` into a helper. Loading a file via the runner that bypassed Vite transformation. Third-party code that tries to feature-detect `import.meta.glob`.
Related errors
- [module runner] Failed to load
- Cannot send non-custom events from the client to the server.
- Cannot send non-custom events from the server to the client.
- [module runner] Dynamic access of "import.meta.env" is not…
- [module runner] "import.meta.resolve" is not supported.
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/05baa4b0e3052cca.
Report an issue: GitHub.
Appendix: source
Thrown at packages/vite/src/module-runner/createImportMeta.ts:30
})
export function createDefaultImportMeta(
modulePath: string,
): ModuleRunnerImportMeta {
const href = posixPathToFileHref(modulePath)
const filename = modulePath
const dirname = posixDirname(modulePath)
return {
filename: isWindows ? toWindowsPath(filename) : filename,
dirname: isWindows ? toWindowsPath(dirname) : dirname,
url: href,
env: envProxy,
resolve(_id: string, _parent?: string) {
throw new Error('[module runner] "import.meta.resolve" is not supported.')
},
// should be replaced during transformation
glob() {
throw new Error(
`[module runner] "import.meta.glob" is statically replaced during ` +
`file transformation. Make sure to reference it by the full name.`,
)
},
}
}
/**
* Create import.meta object for Node.js.
*/
export function createNodeImportMeta(
modulePath: string,
): ModuleRunnerImportMeta {
const defaultMeta = createDefaultImportMeta(modulePath)
const href = defaultMeta.url
const importMetaResolver = createImportMetaResolver()
View on GitHub (pinned to b4d66fee14)