vitejs/vite · error · Error

[module runner] Dynamic access of "import.meta.env" is not…

Error message

[module runner] Dynamic access of "import.meta.env" is not supported. Please, use "import.meta.env.${String(p)}" instead.

What it means

In the module runner, `import.meta.env` is replaced with a Proxy (`envProxy`) whose `get` trap always throws. This is intentional: the runner cannot evaluate arbitrary dynamic property access because env vars must be statically known (they are inlined by Vite during transformation). The error tells you to access a specific property like `import.meta.env.MODE` so the transformer can replace it.

Solutions

  1. Replace dynamic access with a static property reference: `import.meta.env.SOME_NAME`.
  2. If you need a dynamic lookup, map known keys explicitly: `const env = { MODE: import.meta.env.MODE, BASE_URL: import.meta.env.BASE_URL, ... }`.
  3. Use `process.env` or `loadEnv` at config/bootstrap time for runtime-driven env access instead of `import.meta.env[variable]`.
  4. Avoid destructuring/spreading `import.meta.env` as a whole object in runner-executed code.

Example fix

// before
const key = process.env.WHICH
const val = import.meta.env[key]
// after
const val = key === 'MODE' ? import.meta.env.MODE
  : key === 'BASE_URL' ? import.meta.env.BASE_URL
  : undefined
Defensive patterns

Strategy: validation

Validate before calling

// Static analysis check: scan runner-executed source for dynamic import.meta.env access
function hasDynamicImportMetaEnvAccess(src: string): boolean {
  // matches: import.meta.env[  /  = import.meta.env  followed by [
  return /import\.meta\.env\s*\[/.test(src) || /\b\w+\s*=\s*import\.meta\.env\b[\s\S]*?\1\s*\[/.test(src)
}

Try / catch

try {
  return import.meta.env[MODE]
} catch (e) {
  if (e instanceof Error && /Dynamic access of "import.meta.env"/.test(e.message)) {
    // fall back to statically known values
    return undefined
  }
  throw e
}

Prevention

When it happens

Trigger: Code running under the Vite module runner (e.g. SSR environment runner) that accesses `import.meta.env` dynamically: `import.meta.env[dynamicKey]`, `Object.keys(import.meta.env)`, spreading/destructuring the whole object, or `const e = import.meta.env; e[name]`.

Common situations: SSR or module-runner code that enumerates env vars generically (debug utilities, env-dumping libraries). Reading env via a computed key from config. Code originally written for a bundler context where `import.meta.env` is a real object.

Related errors


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

Appendix: source

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

import { isWindows } from '../shared/utils'
import { createImportMetaResolver } from './importMetaResolver'
import type { ModuleRunnerImportMeta } from './types'
import { posixDirname, posixPathToFileHref, toWindowsPath } from './utils'

const envProxy = new Proxy({} as any, {
  get(_, p) {
    throw new Error(
      `[module runner] Dynamic access of "import.meta.env" is not supported. Please, use "import.meta.env.${String(p)}" instead.`,
    )
  },
})

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.')

View on GitHub (pinned to b4d66fee14)