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
- Replace dynamic access with a static property reference: `import.meta.env.SOME_NAME`.
- If you need a dynamic lookup, map known keys explicitly: `const env = { MODE: import.meta.env.MODE, BASE_URL: import.meta.env.BASE_URL, ... }`.
- Use `process.env` or `loadEnv` at config/bootstrap time for runtime-driven env access instead of `import.meta.env[variable]`.
- 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
- Always reference import.meta.env.PROPERTY_NAME literally, never via a variable index.
- Build a fixed allowlist object of the env vars you need instead of enumerating import.meta.env.
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
- Cannot send non-custom events from the client to the server.
- Cannot send non-custom events from the server to the client.
- [module runner] Failed to load
- [module runner] "import.meta.glob" is statically replaced…
- [module runner] "import.meta.resolve" is not supported.
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)