vitejs/vite · error · Error
In virtual modules, all globs must start with '/'
Error message
In virtual modules, all globs must start with '/'
What it means
Thrown by `import.meta.glob` processing when the glob runs inside a virtual module (no on-disk directory / `dir` is falsy) and the glob is relative. Without a directory to resolve relative patterns against, Vite cannot expand them; you must pass absolute globs (starting with `/`) or a `base` option.
Source
Thrown at packages/vite/src/node/plugins/importMetaGlob.ts:457
if (!matches.length) return null
const s = new MagicString(code)
const staticImports = (
await Promise.all(
matches.map(
async ({
globsResolved,
isRelative,
options,
index,
start,
end,
onlyKeys,
onlyValues,
}) => {
if (!dir && !options.base && isRelative) {
throw new Error("In virtual modules, all globs must start with '/'")
}
const cwd = getCommonBase(globsResolved) ?? root
const files = (
await glob(globsResolved, {
absolute: true,
cwd,
dot: !!options.exhaustive,
expandDirectories: false,
caseSensitiveMatch: options.caseSensitive ?? true,
ignore: options.exhaustive ? [] : ['**/node_modules/**'],
extglob: false,
})
)
.filter((file) => file !== id)
.sort()
const objectProps: string[] = []View on GitHub (pinned to 89620f09af)
Solutions
- Use absolute globs starting with `/` rooted at the project root: `import.meta.glob('/src/pages/**/*.vue')`.
- Pass the `base` option so relative globs resolve: `import.meta.glob('./pages/**/*.vue', { base: '/src' })`.
- Move the `import.meta.glob` call into a real on-disk source file rather than a virtual module.
Example fix
// before — called inside a virtual module
const modules = import.meta.glob('./pages/**/*.vue');
// after
const modules = import.meta.glob('/src/pages/**/*.vue'); Defensive patterns
Strategy: validation
Validate before calling
function validateGlobsInVirtualModule(globs, options, isVirtual) {
if (!isVirtual) return;
for (const g of globs) {
if (g.startsWith('/') || g.startsWith('!')) continue;
if (g.startsWith('./') || g.startsWith('../')) {
if (!options?.base) throw new Error(`Relative glob in virtual module needs base or leading '/': ${g}`);
}
}
}
// validateGlobsInVirtualModule(globs, options, id.startsWith('\0') || !id.includes('/')); Type guard
function isVirtualModuleId(id) {
return id.startsWith('\0') || !id.includes('/');
} Prevention
- In virtual modules, always use absolute globs starting with `/`.
- Pass the `base` option when relative globs are unavoidable.
- Prefer placing `import.meta.glob` calls in real source files.
When it happens
Trigger: In the glob transform, `if (!dir && !options.base && isRelative)` is true — i.e. `import.meta.glob('./foo/*.js')` is called from a virtual module id that has no associated directory.
Common situations: Calling `import.meta.glob` with relative patterns from within a virtual module generated by a plugin (e.g. a generated entry), or from code injected by a framework that lacks a real file path.
Related errors
- Invalid glob: "${glob}" (resolved: "${resolved}"). It must s
- { runtime: "${result.runtime}" } is not supported for assets
- `renderLegacyChunks` and `renderModernChunks` cannot be both
- @vitejs/plugin-legacy does not support library mode.
- [module runner] "import.meta.glob" is statically replaced du
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/9e7dc82f8fa20fe1.json.
Report an issue: GitHub.