{"id":"9e7dc82f8fa20fe1","repo":"vitejs/vite","slug":"in-virtual-modules-all-globs-must-start-with","errorCode":null,"errorMessage":"In virtual modules, all globs must start with '/'","messagePattern":"In virtual modules, all globs must start with '/'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/plugins/importMetaGlob.ts","lineNumber":457,"sourceCode":"  if (!matches.length) return null\n\n  const s = new MagicString(code)\n\n  const staticImports = (\n    await Promise.all(\n      matches.map(\n        async ({\n          globsResolved,\n          isRelative,\n          options,\n          index,\n          start,\n          end,\n          onlyKeys,\n          onlyValues,\n        }) => {\n          if (!dir && !options.base && isRelative) {\n            throw new Error(\"In virtual modules, all globs must start with '/'\")\n          }\n\n          const cwd = getCommonBase(globsResolved) ?? root\n          const files = (\n            await glob(globsResolved, {\n              absolute: true,\n              cwd,\n              dot: !!options.exhaustive,\n              expandDirectories: false,\n              caseSensitiveMatch: options.caseSensitive ?? true,\n              ignore: options.exhaustive ? [] : ['**/node_modules/**'],\n              extglob: false,\n            })\n          )\n            .filter((file) => file !== id)\n            .sort()\n\n          const objectProps: string[] = []","sourceCodeStart":439,"sourceCodeEnd":475,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/node/plugins/importMetaGlob.ts#L439-L475","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — called inside a virtual module\nconst modules = import.meta.glob('./pages/**/*.vue');\n// after\nconst modules = import.meta.glob('/src/pages/**/*.vue');","handlingStrategy":"validation","validationCode":"function validateGlobsInVirtualModule(globs, options, isVirtual) {\n  if (!isVirtual) return;\n  for (const g of globs) {\n    if (g.startsWith('/') || g.startsWith('!')) continue;\n    if (g.startsWith('./') || g.startsWith('../')) {\n      if (!options?.base) throw new Error(`Relative glob in virtual module needs base or leading '/': ${g}`);\n    }\n  }\n}\n// validateGlobsInVirtualModule(globs, options, id.startsWith('\\0') || !id.includes('/'));","typeGuard":"function isVirtualModuleId(id) {\n  return id.startsWith('\\0') || !id.includes('/');\n}","tryCatchPattern":null,"preventionTips":["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."],"tags":["import-meta-glob","virtual-module","config"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}