{"id":"50f32a04a4dd9d1f","repo":"vitejs/vite","slug":"invalid-glob-glob-resolved-resolved","errorCode":null,"errorMessage":"Invalid glob: \"${glob}\" (resolved: \"${resolved}\"). It must start with '/' or './'","messagePattern":"Invalid glob: \"(.+?)\" \\(resolved: \"(.+?)\"\\)\\. It must start with '/' or '\\./'","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/plugins/importMetaGlob.ts","lineNumber":687,"sourceCode":"  }\n\n  if (glob[0] === '/') return pre + posix.join(root, glob.slice(1))\n  if (glob.startsWith('./')) return pre + posix.join(dir, glob.slice(2))\n  if (glob.startsWith('../')) return pre + posix.join(dir, glob)\n  if (glob.startsWith('**')) return pre + glob\n\n  const isSubImportsPattern = glob[0] === '#' && glob.includes('*')\n\n  const resolved = normalizePath(\n    (await resolveId(glob, importer, {\n      custom: { 'vite:import-glob': { isSubImportsPattern } },\n    })) || glob,\n  )\n  if (isAbsolute(resolved)) {\n    return pre + globSafeResolvedPath(resolved, glob)\n  }\n\n  throw new Error(\n    `Invalid glob: \"${glob}\" (resolved: \"${resolved}\"). It must start with '/' or './'`,\n  )\n}\n\nexport function getCommonBase(globsResolved: string[]): null | string {\n  const bases = globsResolved\n    .filter((g) => g[0] !== '!')\n    .map((glob) => {\n      let { base } = picomatch.scan(glob)\n      // `scan('a/foo.js')` returns `base: 'a/foo.js'`\n      if (posix.basename(base).includes('.')) base = posix.dirname(base)\n\n      return base\n    })\n\n  if (!bases.length) return null\n\n  let commonAncestor = ''","sourceCodeStart":669,"sourceCodeEnd":705,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/node/plugins/importMetaGlob.ts#L669-L705","documentation":"Thrown when resolving a single `import.meta.glob` pattern whose specifier is neither absolute nor made relative (`./`/`../`). After attempting to resolve the pattern via the resolve pipeline, if the result does not start with `/`, Vite rejects it because glob patterns must be path-rooted to be expanded safely.","triggerScenarios":"In `await resolveId(glob, importer, ...)`, the resolved value is not absolute (`isAbsolute(resolved)` is false) — e.g. a bare package specifier that did not resolve to a file path, or a glob that resolves to a relative/bare string.","commonSituations":"Globbing a bare package import (`import.meta.glob('lodash/*.js')`) where the package cannot be resolved to an absolute path; subpath patterns that don't resolve; a glob missing a leading `./` or `/`.","solutions":["Prefix the glob with `/` (absolute from project root) or `./` (relative to the importing file).","If globbing inside a package, ensure the package is installed and its exports resolve; use a subpath pattern with leading `./`.","Avoid bare-specifier globs; resolve to a concrete path first."],"exampleFix":"// before\nconst modules = import.meta.glob('components/*.vue');\n// after\nconst modules = import.meta.glob('./components/*.vue');","handlingStrategy":"validation","validationCode":"function validateGlobPattern(glob) {\n  if (glob.startsWith('/') || glob.startsWith('./') || glob.startsWith('../') || glob.startsWith('!')) return;\n  throw new Error(`Glob must start with '/' or './': ${glob}`);\n}\n// globs.forEach(validateGlobPattern);","typeGuard":"function isValidGlobPrefix(glob) {\n  return /^(\\/|\\.\\/|\\.\\.\\/|!)/.test(glob);\n}","tryCatchPattern":null,"preventionTips":["Always prefix glob patterns with `/` (absolute) or `./` (relative).","Avoid bare package-specifier globs; resolve them to concrete paths first.","Add an ESLint/custom check banning `import.meta.glob('...')` without a `./` or `/` prefix."],"tags":["import-meta-glob","resolve","config"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}