vitejs/vite · error · Error

"local" cannot be used as a mode name because it conflicts w

Error message

"local" cannot be used as a mode name because it conflicts with the .local postfix for .env files.

What it means

`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.

Source

Thrown at packages/vite/src/node/env.ts:42

  }

  return []
}

/**
 * Load `.env` files within the `envDir` and merge them with the matching
 * variables already present in `process.env`.
 */
export function loadEnv(
  mode: string,
  envDir: string | false,
  prefixes: string | string[] = 'VITE_',
): Record<string, string> {
  const start = performance.now()
  const getTime = () => `${(performance.now() - start).toFixed(2)}ms`

  if (mode === 'local') {
    throw new Error(
      `"local" cannot be used as a mode name because it conflicts with ` +
        `the .local postfix for .env files.`,
    )
  }
  prefixes = arraify(prefixes)
  const env: Record<string, string> = {}
  const envFiles = getEnvFilesForMode(mode, envDir)

  debug?.(`loading env files: %O`, envFiles)

  const parsed = Object.fromEntries(
    envFiles.flatMap((filePath) => {
      const stat = tryStatSync(filePath)
      // Support FIFOs (named pipes) for apps like 1Password
      if (!stat || (!stat.isFile() && !stat.isFIFO())) return []

      const parsedEnv = parseEnv(fs.readFileSync(filePath, 'utf-8'))
      return Object.entries(parsedEnv as Record<string, string>)

View on GitHub (pinned to 89620f09af)

Solutions

  1. Pick a non-reserved mode name such as `development`, `dev-local`, `localhost`, or `local-dev`.
  2. If you wanted machine-specific overrides, keep `mode: 'development'` and put secrets in `.env.local` (which Vite loads automatically).
  3. Audit scripts/CI for `--mode local` and rename the mode variable.

Example fix

// before
loadEnv('local', process.cwd())
// vite build --mode local

// after
loadEnv('development', process.cwd())
// vite build --mode development
Defensive patterns

Strategy: validation

Validate before calling

const RESERVED_MODES = new Set(['local'])
function assertMode(mode: string) {
  if (RESERVED_MODES.has(mode)) throw new Error(`Mode '${mode}' is reserved; use 'development' or a custom name`)
}

Type guard

function isValidMode(mode: string): boolean {
  return mode !== 'local' && /^[a-z0-9-]+$/i.test(mode)
}

Prevention

When it happens

Trigger: Calling `loadEnv('local', ...)` directly, running `vite build --mode local`, or programmatically starting a server/preview with `mode: 'local'`.

Common situations: 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.

Related errors


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