vitejs/vite · error · Error

Invalid glob: "${glob}" (resolved: "${resolved}"). It must s

Error message

Invalid glob: "${glob}" (resolved: "${resolved}"). It must start with '/' or './'

What it means

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.

Source

Thrown at packages/vite/src/node/plugins/importMetaGlob.ts:687

  }

  if (glob[0] === '/') return pre + posix.join(root, glob.slice(1))
  if (glob.startsWith('./')) return pre + posix.join(dir, glob.slice(2))
  if (glob.startsWith('../')) return pre + posix.join(dir, glob)
  if (glob.startsWith('**')) return pre + glob

  const isSubImportsPattern = glob[0] === '#' && glob.includes('*')

  const resolved = normalizePath(
    (await resolveId(glob, importer, {
      custom: { 'vite:import-glob': { isSubImportsPattern } },
    })) || glob,
  )
  if (isAbsolute(resolved)) {
    return pre + globSafeResolvedPath(resolved, glob)
  }

  throw new Error(
    `Invalid glob: "${glob}" (resolved: "${resolved}"). It must start with '/' or './'`,
  )
}

export function getCommonBase(globsResolved: string[]): null | string {
  const bases = globsResolved
    .filter((g) => g[0] !== '!')
    .map((glob) => {
      let { base } = picomatch.scan(glob)
      // `scan('a/foo.js')` returns `base: 'a/foo.js'`
      if (posix.basename(base).includes('.')) base = posix.dirname(base)

      return base
    })

  if (!bases.length) return null

  let commonAncestor = ''

View on GitHub (pinned to 89620f09af)

Solutions

  1. Prefix the glob with `/` (absolute from project root) or `./` (relative to the importing file).
  2. If globbing inside a package, ensure the package is installed and its exports resolve; use a subpath pattern with leading `./`.
  3. Avoid bare-specifier globs; resolve to a concrete path first.

Example fix

// before
const modules = import.meta.glob('components/*.vue');
// after
const modules = import.meta.glob('./components/*.vue');
Defensive patterns

Strategy: validation

Validate before calling

function validateGlobPattern(glob) {
  if (glob.startsWith('/') || glob.startsWith('./') || glob.startsWith('../') || glob.startsWith('!')) return;
  throw new Error(`Glob must start with '/' or './': ${glob}`);
}
// globs.forEach(validateGlobPattern);

Type guard

function isValidGlobPrefix(glob) {
  return /^(\/|\.\/|\.\.\/|!)/.test(glob);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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 `/`.

Related errors


AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03). Data as JSON: /data/errors/50f32a04a4dd9d1f.json. Report an issue: GitHub.