vitejs/vite · error · Error

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

Error message

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

What it means

Thrown by the module runner's default import.meta.env proxy when any property is accessed dynamically. In the module runner (SSR/runtime), import.meta.env is a Proxy whose get trap always throws because env variables are meant to be statically replaced at transform time (e.g., import.meta.env.SSR becomes true/false). Dynamic access like import.meta.env[variableName] or Object.keys(import.meta.env) cannot be statically analyzed and thus hits the proxy trap.

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 89620f09af)

Solutions

  1. Replace dynamic env access with static property access: use import.meta.env.SSR, import.meta.env.DEV, etc., directly in code so the transformer can statically replace them.
  2. If you need to read a custom env variable, reference it by its full static name: import.meta.env.VITE_MY_VAR.
  3. If iterating env is unavoidable, read the values into a plain object at build time and import that object instead.
  4. For libraries doing generic env enumeration, guard with typeof import.meta.env checks or use a different mechanism in SSR contexts.

Example fix

// before — dynamic access fails in module runner
const key = 'SSR'
const isSSR = import.meta.env[key]
// after — static access is statically replaced
const isSSR = import.meta.env.SSR
Defensive patterns

Strategy: validation

Validate before calling

// Detect dynamic import.meta.env access patterns in source before running
// Use a lint rule or pre-build check
import { readFileSync } from 'fs'
function checkForDynamicEnvAccess(filePath) {
  const code = readFileSync(filePath, 'utf-8')
  // flag computed member access on import.meta.env
  if (/import\.meta\.env\s*\[/.test(code)) {
    console.warn(`${filePath}: dynamic import.meta.env[...] access will fail in module runner`)
  }
}

Type guard

// Type-level guard: use 'as const' or explicit keys
type ViteEnvKey = 'SSR' | 'DEV' | 'PROD' | 'MODE' | 'BASE_URL'
function getEnv(key: ViteEnvKey): any {
  // forces static, known key access
  return import.meta.env[key] // still dynamic at runtime — avoid this pattern
}
// Instead, use direct: import.meta.env.SSR

Try / catch

// In module runner code, avoid try-catch; fix the access pattern instead
// If wrapping third-party code:
const safeEnv = new Proxy(import.meta.env, {
  get(target, prop) {
    // provide static values for known keys
    return { SSR: false, DEV: true, PROD: false, MODE: 'development', BASE_URL: '/' }[prop]
  }
})

Prevention

When it happens

Trigger: Code running in the Vite module runner (SSR environment, Vitest with SSR) that accesses import.meta.env via computed property: import.meta.env[someVar], destructuring with computed keys, or iterating over import.meta.env. Also triggered by libraries that generically enumerate env objects.

Common situations: Server-side code that tries to iterate or dynamically read env variables. A shared utility used in both client and server that does Object.entries(import.meta.env) or import.meta.env[key]. Framework-level env access patterns that work in browser builds (where env is statically replaced) but fail in SSR module runner.

Related errors


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