You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In Nuxt v4.3.0, you could pass multiple .env files on the CLI like this:
nuxt dev --dotenv .env.development --dotenv .env.local
Since Nuxt v4.3.1, this no longer works and only one --dotenv argument is accepted.
There may be cases where someone wants to use multiple files, for example a .env.local for sensitive API keys and a .env.development for non-sensitive configuration data like DB URLs.
Since the config in .env.development is only for dev and would result in a broken application in prod, it doesn't make much sense semantically to put its contents into a .env file.
The solution could be implemented with a separator, like this (although I have to admit it looks a bit ugly):
nuxt dev --dotenv .env.development,.env.local
Additional information
Would you be willing to help implement this feature?
It is an upstream issue... citty v0.2.0 replaced its custom parser with Node.js's native util.parseArgs.
Workaround
Use dotenv-cli and pass in your list of env files:
dotenv -e .env.development -e .env -- nuxt dev
Root Cause Analysis
The bug has three layers, each responsible to a different package.
Layer 1 β node:util.parseArgs: the multiple flag
Node.js's built-in util.parseArgs (introduced in v18.3, stable in v20) has a multiple option per argument. When it's false (the default), repeated flags use last-wins semantics:
Layer 2 β citty 0.2.x: never sets multiple: true
In citty v0.2.0, the custom arg parser was replaced with node:util.parseArgs. The problem is that in _parser.ts, when citty builds the options object passed to util.parseArgs, it never sets multiple: true for any arg type. You can see exactly this in the source:
// From citty's parseRawArgs() in dist/index.mjsfor(constnameofallOptions){if(!options[name])options[name]={type: getType(name),// 'boolean' or 'string'default: defaults[name]// β no `multiple: true` ever};}
Before v0.2.0, citty had its own hand-rolled parser that accumulated repeated flags into arrays. The switch to util.parseArgssilently dropped that behavior.
Layer 3 β nuxi (@nuxt/cli): dotenv defined as plain type: "string"
In nuxi's shared args definition:
// node_modules/nuxi/dist/_shared-*.mjsconstdotEnvArgs={dotenv: {type: "string",description: "Path to `.env` file to load, relative to the root directory"}};
dotenv is a plain string arg with no indication that it should be repeatable. Even if citty did support a multiple field, nuxi doesn't set it.
Activity
OrbisK commentedon Mar 13, 2026
This might be an upstream issue at https://github.com/unjs/citty
antonyharfield commentedon May 18, 2026
It is an upstream issue... citty v0.2.0 replaced its custom parser with Node.js's native
util.parseArgs.Workaround
Use
dotenv-cliand pass in your list of env files:Root Cause Analysis
The bug has three layers, each responsible to a different package.
Layer 1 β
node:util.parseArgs: themultipleflagNode.js's built-in
util.parseArgs(introduced in v18.3, stable in v20) has amultipleoption per argument. When it'sfalse(the default), repeated flags use last-wins semantics:When
multiple: true, all values are collected into an array:Layer 2 β
citty 0.2.x: never setsmultiple: trueIn citty v0.2.0, the custom arg parser was replaced with
node:util.parseArgs. The problem is that in_parser.ts, when citty builds theoptionsobject passed toutil.parseArgs, it never setsmultiple: truefor any arg type. You can see exactly this in the source:Before v0.2.0, citty had its own hand-rolled parser that accumulated repeated flags into arrays. The switch to
util.parseArgssilently dropped that behavior.Layer 3 β
nuxi(@nuxt/cli):dotenvdefined as plaintype: "string"In nuxi's shared args definition:
dotenvis a plainstringarg with no indication that it should be repeatable. Even if citty did support amultiplefield, nuxi doesn't set it.danielroe commentedon Jul 27, 2026
this will need unjs/citty#258 to be implemented first. possibly via unjs/citty#259.