vitejs/vite · error · Error
"local" cannot be used as a mode name because it conflicts…
Error message
"local" cannot be used as a mode name because it conflicts with the .local postfix for .env files.
What it means
loadEnv reserves the mode name 'local' because Vite appends .local to env filenames for local overrides (e.g. .env.development.local). If 'local' were a mode, .env.local would collide with .env.<mode> resolution, so loadEnv rejects it up front.
Solutions
- Pick a different mode name (e.g. development-local, staging) that does not collide with the .local suffix.
- Use .env.<mode>.local files for local overrides instead of a 'local' mode.
- If you only need a local override, leave mode as development and create .env.local.
Example fix
// before vite build --mode local // after vite build --mode dev-local
Defensive patterns
Strategy: validation
Validate before calling
function validateMode(mode) {
if (mode === 'local') return 'Mode "local" is reserved';
return null;
} Type guard
function isAllowedMode(mode) { return mode && mode !== 'local'; } Prevention
- Never use --mode local; rely on .env.<mode>.local files for overrides.
- Validate programmatic mode values against a reserved-words list.
When it happens
Trigger: Calling loadEnv('local', envDir) or starting Vite with --mode local. The check fires before any env file is read.
Common situations: CI or staging scripts that pass --mode local thinking it triggers local-only behavior; programmatic callers looping over a list of modes that includes 'local'.
Related errors
- envPrefix option contains value '', which could lead…
- config must export or return an object.
- currently full bundle mode is only available for client…
- Environment " " is not defined in the config.
- Environment " " is not defined in the config.
AI-assisted analysis of vitejs/vite@b4d66fee14 (2026-08-11).
Data as JSON: /api/errors/4ac5cd05813f942d.
Report an issue: GitHub.
Appendix: 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 b4d66fee14)