{"record":{"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/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/plugins/importMetaGlob.ts#L669-L705","documentation":"resolveGlobPattern normalizes a single glob. It accepts globs starting with '/', './', '../', or '**', and tries to resolve anything else as a module id. If that resolution does not produce an absolute path, the glob is unusable and Vite throws, echoing both the raw glob and the resolved value.","triggerScenarios":"Passing import.meta.glob a bare specifier (e.g. 'foo/*.js') or a path that neither matches the recognized prefixes nor resolves to an absolute module path. Also triggered by typos like 'src/x' (no leading './').","commonSituations":"Users assuming bare globs resolve like Node imports, copy-paste glob strings missing the './' prefix, or globs pointing at packages that are not installed (so resolveId returns the bare string unchanged, which is not absolute).","solutions":["Prefix the glob with './' for relative imports or '/' for absolute-from-root.","If importing from a package, install/verify the package so resolveId returns an absolute path.","For '#' subpath imports ensure the target exports map resolves; otherwise switch to an explicit relative/absolute glob.","Check the printed 'resolved' value in the error — if it equals the raw glob, resolution failed entirely."],"exampleFix":"// before\nconst mods = import.meta.glob('src/widgets/*.vue')\n// after\nconst mods = import.meta.glob('./widgets/*.vue')\n// or\nconst mods = import.meta.glob('/src/widgets/*.vue')","handlingStrategy":"validation","validationCode":"function validateGlob(glob) {\n  if (glob.startsWith('/') || glob.startsWith('./') || glob.startsWith('../') || glob.startsWith('**')) return\n  // bare spec: ensure it resolves\n  // (caller checks resolveId result is absolute before passing on)\n  throw new Error(`Glob must start with '/', './', '../', or '**': ${glob}`)\n}","typeGuard":"function isWellFormedGlob(glob): boolean {\n  return glob.startsWith('/') || glob.startsWith('./') || glob.startsWith('../') || glob.startsWith('**')\n}","tryCatchPattern":null,"preventionTips":["Always prefix relative globs with './'.","Use '/' for root-anchored globs.","Run a quick lint pass over import.meta.glob arguments in CI."],"tags":["glob","import-meta-glob","config"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}