From b2429cc2d20cd60127bc36a3749cda1943f07cd8 Mon Sep 17 00:00:00 2001 From: sangwook Date: Thu, 7 May 2026 23:47:20 +0000 Subject: [PATCH 1/2] src: support override option in process.loadEnvFile Add an opt-in `override` option to `process.loadEnvFile()` and a matching `--env-file-override-local` CLI flag, allowing values from `.env` files to replace existing variables in `process.env`. By default, existing environment variables continue to take precedence; callers must opt in explicitly. This lets a single process swap env-file contexts at runtime (integration tests, monorepo configurations) without manually parsing files via `util.parseEnv()`. Co-authored-by: Ilyas Shabi Signed-off-by: sangwook --- doc/api/cli.md | 21 +++++ doc/api/process.md | 40 +++++++++- doc/node.1 | 8 ++ lib/internal/process/per_thread.js | 26 ++++++- src/node.cc | 3 +- src/node_dotenv.cc | 4 +- src/node_dotenv.h | 2 +- src/node_options.cc | 5 ++ src/node_options.h | 1 + src/node_process_methods.cc | 6 +- test/fixtures/dotenv/assert-basic.js | 5 ++ .../dotenv/load-env-file-no-override.js | 7 ++ .../dotenv/load-env-file-options-only.js | 7 ++ .../fixtures/dotenv/load-env-file-override.js | 7 ++ test/parallel/test-process-load-env-file.js | 76 +++++++++++++++++++ 15 files changed, 206 insertions(+), 12 deletions(-) create mode 100644 test/fixtures/dotenv/assert-basic.js create mode 100644 test/fixtures/dotenv/load-env-file-no-override.js create mode 100644 test/fixtures/dotenv/load-env-file-options-only.js create mode 100644 test/fixtures/dotenv/load-env-file-override.js diff --git a/doc/api/cli.md b/doc/api/cli.md index 80f2fa74818b92..7f4b7025583280 100644 --- a/doc/api/cli.md +++ b/doc/api/cli.md @@ -937,6 +937,26 @@ changes: Behavior is the same as [`--env-file`][], but an error is not thrown if the file does not exist. +### `--env-file-override-local` + + + +By default, when a variable defined in an env file is already set in the +environment, the existing value is preserved. Pass +`--env-file-override-local` together with [`--env-file`][] (or +[`--env-file-if-exists`][]) to make values from the file override existing +environment variables instead. + +```bash +BASIC=local node --env-file=.env --env-file-override-local -p 'process.env.BASIC' +# prints the value from .env, not 'local'. +``` + +To override variables at runtime, use the `override` option of +[`process.loadEnvFile()`][]. + ### `--env-file=file` -* `path` {string | URL | Buffer | undefined}. **Default:** `'./.env'` +* `path` {string | URL | Buffer | undefined} **Default:** `'./.env'` +* `options` {Object} + * `override` {boolean} If `true`, values from the file replace any matching + variable already set in `process.env`. **Default:** `false`. Loads the `.env` file into `process.env`. Usage of `NODE_OPTIONS` in the `.env` file will not have any effect on Node.js. @@ -2782,6 +2785,38 @@ import { loadEnvFile } from 'node:process'; loadEnvFile(); ``` +By default, an env file does not override variables that are already set. +Pass `override: true` to replace them with the values from the file: + +```cjs +const { loadEnvFile } = require('node:process'); +// process.env.API_KEY === 'local-key' +loadEnvFile('.env', { override: true }); +// process.env.API_KEY now matches the value from .env +``` + +```mjs +import { loadEnvFile } from 'node:process'; +// process.env.API_KEY === 'local-key' +loadEnvFile('.env', { override: true }); +// process.env.API_KEY now matches the value from .env +``` + +When called with options only, the default `'./.env'` path is used: + +```cjs +const { loadEnvFile } = require('node:process'); +loadEnvFile({ override: true }); +``` + +```mjs +import { loadEnvFile } from 'node:process'; +loadEnvFile({ override: true }); +``` + +The same behavior is available at startup via the +[`--env-file-override-local`][] flag. + ## `process.mainModule`