vitejs/vite · error · Error

[module runner] "import.meta.glob" is statically replaced…

Error message

[module runner] "import.meta.glob" is statically replaced during file transformation. Make sure to reference it by the full name.

What it means

`import.meta.glob` is not a real runtime function - Vite statically transforms it into an import map during file transformation. If the call survives to the module runner (i.e. the proxy/placeholder `glob()` throws), it means the transform did not replace it, almost always because the code references it indirectly (via a renamed alias, a variable, `window['import.meta.glob']`-style access, or code that the Vite plugin pipeline never processed).

Solutions

  1. Always call `import.meta.glob(...)` by its full name inline at the use site so Vite's transform can see and replace it.
  2. If you need a reusable helper, write a wrapper module that calls `import.meta.glob` and re-exports the result - do not pass the function itself around.
  3. Ensure the file is actually transformed by Vite (imported through the Vite module graph, not read via raw fs/Node).

Example fix

// before - aliased, transform cannot see it
const glob = import.meta.glob
const mods = glob('./pages/*.vue')

// after - inline full name
const mods = import.meta.glob('./pages/*.vue')
Defensive patterns

Strategy: validation

Validate before calling

// Lint: flag aliasing/indirection of import.meta.glob in runner-executed code
function hasAliasedImportMetaGlob(src: string): boolean {
  return /(?:const|let|var)\s+\w+\s*=\s*import\.meta\.glob\b/.test(src)
    || /import\.meta\.glob\b(?!\s*\()/.test(src)
}

Try / catch

try {
  import.meta.glob('./pages/*.vue')
} catch (e) {
  if (e instanceof Error && /import.meta.glob.*statically replaced/.test(e.message)) {
    // rewrite call site to use the full name inline
  } else throw e
}

Prevention

When it happens

Trigger: Aliasing `import.meta.glob` to a short variable (`const g = import.meta.glob; g(...)`), passing it as a callback, string-looking it up, or executing code outside Vite's transform pipeline (raw Node import, a precompiled file not run through Vite). The throw fires from the default import meta's `glob()` stub.

Common situations: Refactors that extract `import.meta.glob` into a helper. Loading a file via the runner that bypassed Vite transformation. Third-party code that tries to feature-detect `import.meta.glob`.

Related errors


AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11). Data as JSON: /api/errors/05baa4b0e3052cca. Report an issue: GitHub.

Appendix: source

Thrown at packages/vite/src/module-runner/createImportMeta.ts:30

})

export function createDefaultImportMeta(
  modulePath: string,
): ModuleRunnerImportMeta {
  const href = posixPathToFileHref(modulePath)
  const filename = modulePath
  const dirname = posixDirname(modulePath)
  return {
    filename: isWindows ? toWindowsPath(filename) : filename,
    dirname: isWindows ? toWindowsPath(dirname) : dirname,
    url: href,
    env: envProxy,
    resolve(_id: string, _parent?: string) {
      throw new Error('[module runner] "import.meta.resolve" is not supported.')
    },
    // should be replaced during transformation
    glob() {
      throw new Error(
        `[module runner] "import.meta.glob" is statically replaced during ` +
          `file transformation. Make sure to reference it by the full name.`,
      )
    },
  }
}

/**
 * Create import.meta object for Node.js.
 */
export function createNodeImportMeta(
  modulePath: string,
): ModuleRunnerImportMeta {
  const defaultMeta = createDefaultImportMeta(modulePath)
  const href = defaultMeta.url

  const importMetaResolver = createImportMetaResolver()

View on GitHub (pinned to b4d66fee14)