{"id":"2e4fc6d8e170b50f","repo":"vitejs/vite","slug":"module-runner-dynamic-access-of-import-meta-env","errorCode":null,"errorMessage":"[module runner] Dynamic access of \"import.meta.env\" is not supported. Please, use \"import.meta.env.${String(p)}\" instead.","messagePattern":"\\[module runner\\] Dynamic access of \"import\\.meta\\.env\" is not supported\\. Please, use \"import\\.meta\\.env\\.(.+?)\" instead\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/module-runner/createImportMeta.ts","lineNumber":8,"sourceCode":"import { isWindows } from '../shared/utils'\nimport { createImportMetaResolver } from './importMetaResolver'\nimport type { ModuleRunnerImportMeta } from './types'\nimport { posixDirname, posixPathToFileHref, toWindowsPath } from './utils'\n\nconst envProxy = new Proxy({} as any, {\n  get(_, p) {\n    throw new Error(\n      `[module runner] Dynamic access of \"import.meta.env\" is not supported. Please, use \"import.meta.env.${String(p)}\" instead.`,\n    )\n  },\n})\n\nexport function createDefaultImportMeta(\n  modulePath: string,\n): ModuleRunnerImportMeta {\n  const href = posixPathToFileHref(modulePath)\n  const filename = modulePath\n  const dirname = posixDirname(modulePath)\n  return {\n    filename: isWindows ? toWindowsPath(filename) : filename,\n    dirname: isWindows ? toWindowsPath(dirname) : dirname,\n    url: href,\n    env: envProxy,\n    resolve(_id: string, _parent?: string) {\n      throw new Error('[module runner] \"import.meta.resolve\" is not supported.')","sourceCodeStart":1,"sourceCodeEnd":26,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/module-runner/createImportMeta.ts#L1-L26","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — dynamic access fails in module runner\nconst key = 'SSR'\nconst isSSR = import.meta.env[key]\n// after — static access is statically replaced\nconst isSSR = import.meta.env.SSR","handlingStrategy":"validation","validationCode":"// Detect dynamic import.meta.env access patterns in source before running\n// Use a lint rule or pre-build check\nimport { readFileSync } from 'fs'\nfunction checkForDynamicEnvAccess(filePath) {\n  const code = readFileSync(filePath, 'utf-8')\n  // flag computed member access on import.meta.env\n  if (/import\\.meta\\.env\\s*\\[/.test(code)) {\n    console.warn(`${filePath}: dynamic import.meta.env[...] access will fail in module runner`)\n  }\n}","typeGuard":"// Type-level guard: use 'as const' or explicit keys\ntype ViteEnvKey = 'SSR' | 'DEV' | 'PROD' | 'MODE' | 'BASE_URL'\nfunction getEnv(key: ViteEnvKey): any {\n  // forces static, known key access\n  return import.meta.env[key] // still dynamic at runtime — avoid this pattern\n}\n// Instead, use direct: import.meta.env.SSR","tryCatchPattern":"// In module runner code, avoid try-catch; fix the access pattern instead\n// If wrapping third-party code:\nconst safeEnv = new Proxy(import.meta.env, {\n  get(target, prop) {\n    // provide static values for known keys\n    return { SSR: false, DEV: true, PROD: false, MODE: 'development', BASE_URL: '/' }[prop]\n  }\n})","preventionTips":["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."],"tags":["module-runner","import-meta-env","ssr","static-analysis"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}