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
- 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.
- If you need to read a custom env variable, reference it by its full static name: import.meta.env.VITE_MY_VAR.
- If iterating env is unavoidable, read the values into a plain object at build time and import that object instead.
- 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
- Always access import.meta.env properties by their literal static name (e.g., import.meta.env.SSR).
- Never use computed property access or iteration on import.meta.env.
- Audit third-party dependencies for dynamic env access patterns when used in SSR.
- Add an ESLint custom rule to flag import.meta.env[ dynamic access.
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
- [module runner] "import.meta.resolve" is not supported.
- [module runner] "import.meta.glob" is statically replaced du
- Vite module runner has been closed.
- Module "${url}" was mistakenly invalidated during fetch phas
- [module runner] Failed to load "${url}"${importer ? ` import
AI-assisted analysis of vitejs/vite@89620f09af (2026-08-03).
Data as JSON: /data/errors/2e4fc6d8e170b50f.json.
Report an issue: GitHub.