{"id":"4ac5cd05813f942d","repo":"vitejs/vite","slug":"local-cannot-be-used-as-a-mode-name-because-it-c","errorCode":null,"errorMessage":"\"local\" cannot be used as a mode name because it conflicts with the .local postfix for .env files.","messagePattern":"\"local\" cannot be used as a mode name because it conflicts with the \\.local postfix for \\.env files\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/env.ts","lineNumber":42,"sourceCode":"  }\n\n  return []\n}\n\n/**\n * Load `.env` files within the `envDir` and merge them with the matching\n * variables already present in `process.env`.\n */\nexport function loadEnv(\n  mode: string,\n  envDir: string | false,\n  prefixes: string | string[] = 'VITE_',\n): Record<string, string> {\n  const start = performance.now()\n  const getTime = () => `${(performance.now() - start).toFixed(2)}ms`\n\n  if (mode === 'local') {\n    throw new Error(\n      `\"local\" cannot be used as a mode name because it conflicts with ` +\n        `the .local postfix for .env files.`,\n    )\n  }\n  prefixes = arraify(prefixes)\n  const env: Record<string, string> = {}\n  const envFiles = getEnvFilesForMode(mode, envDir)\n\n  debug?.(`loading env files: %O`, envFiles)\n\n  const parsed = Object.fromEntries(\n    envFiles.flatMap((filePath) => {\n      const stat = tryStatSync(filePath)\n      // Support FIFOs (named pipes) for apps like 1Password\n      if (!stat || (!stat.isFile() && !stat.isFIFO())) return []\n\n      const parsedEnv = parseEnv(fs.readFileSync(filePath, 'utf-8'))\n      return Object.entries(parsedEnv as Record<string, string>)","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/vitejs/vite/blob/89620f09afcfef6b35e7bb8660132ab5b4d0cd3b/packages/vite/src/node/env.ts#L24-L60","documentation":"`loadEnv` rejects the literal mode string `\"local\"` because Vite reserves the `.local` suffix for git-ignored override files (`.env.local`, `.env.<mode>.local`). Using `local` as a mode would collide: `.env.local` would be ambiguous between the mode file and the always-local override, and `getEnvFilesForMode` already lists `.env.local` unconditionally. The guard at env.ts:41 prevents the ambiguity.","triggerScenarios":"Calling `loadEnv('local', ...)` directly, running `vite build --mode local`, or programmatically starting a server/preview with `mode: 'local'`.","commonSituations":"Teams naming environments after machines or stages (dev/local/staging); CI configs that pass `MODE=local`; scaffold templates that default to a `local` mode name.","solutions":["Pick a non-reserved mode name such as `development`, `dev-local`, `localhost`, or `local-dev`.","If you wanted machine-specific overrides, keep `mode: 'development'` and put secrets in `.env.local` (which Vite loads automatically).","Audit scripts/CI for `--mode local` and rename the mode variable."],"exampleFix":"// before\nloadEnv('local', process.cwd())\n// vite build --mode local\n\n// after\nloadEnv('development', process.cwd())\n// vite build --mode development","handlingStrategy":"validation","validationCode":"const RESERVED_MODES = new Set(['local'])\nfunction assertMode(mode: string) {\n  if (RESERVED_MODES.has(mode)) throw new Error(`Mode '${mode}' is reserved; use 'development' or a custom name`)\n}","typeGuard":"function isValidMode(mode: string): boolean {\n  return mode !== 'local' && /^[a-z0-9-]+$/i.test(mode)\n}","tryCatchPattern":null,"preventionTips":["Treat 'local' as a reserved word in your env/mode tooling.","Use .env.local for machine overrides rather than a 'local' mode."],"tags":["env","config","mode","validation"],"analyzedSha":"89620f09afcfef6b35e7bb8660132ab5b4d0cd3b","analyzedAt":"2026-08-03T19:28:02.920Z","schemaVersion":2}