-
Notifications
You must be signed in to change notification settings - Fork 3.5k
[BUG] Impossible to reliably passthrough NODE_OPTIONS in .npmrc #8335
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Note to maintainers: this is the same behavior in npm 10.8.2 EDIT: I do agree with the author of the issue |
I am writing to express my interest in addressing the issue involving environment variable substitution in .npmrc—specifically, how ${NODE_OPTIONS} behaves when the variable is undefined. This behavior currently causes Node.js to fail or ignore critical flags due to incorrect string substitution, which leads to unreliable configurations for developers. The Problem When node-options = "${NODE_OPTIONS} --max-old-space-size=1" is used in .npmrc, it works as expected only if NODE_OPTIONS is already set. However, if it's not defined at all, the placeholder is passed literally as ${NODE_OPTIONS}, causing Node.js to reject or ignore all flags. This behavior breaks consistency and creates potential runtime issues. |
The entire replacement boils down to https://github.com/npm/cli/blob/latest/workspaces/config/lib/env-replace.js file which has a simple code for replacing env vars after I reckoned that existing projects might rely on the variables not being replaced if the value is not defined so silently changing the code to evaluate to empty string if the env var is undefined might not be a good idea. Then I considered what would it take to implement So after all, since the syntax is custom anyway, I though that simple and reliable solution would be to introduce a Summary of the idea:
|
try updating the env-replace.js logic to support optional environment
variables using the ${VAR?} syntax. This means:
${FOO} works the same as before.
${FOO?} now safely evaluates to an empty string if FOO is undefined.
This avoids breaking existing behavior while offering more flexibility. It
also handles escaped expressions like \${FOO} correctly.
…On Fri, May 30, 2025 at 1:33 PM Arkadiusz Czekajski < ***@***.***> wrote:
*aczekajski* left a comment (npm/cli#8335)
<#8335 (comment)>
The entire replacement boils down to
https://github.com/npm/cli/blob/latest/workspaces/config/lib/env-replace.js
file which has a simple code for replacing env vars after ini package
parses the config.
I reckoned that existing projects might rely on the variables not being
replaced if the value is not defined so silently changing the code to
evaluate to empty string if the env var is undefined might not be a good
idea.
Then I considered what would it take to implement ${FOO:default} syntax
and quickly relized that it falls into a parsing and escaping hell (what if
someone wants to default to string that contains } or \\ or \\} etc).
HAving defaults would be nice but solving the original problem doesn't need
it.
So after all, since the syntax is custom anyway, I though that simple and
reliable solution would be to introduce a ? modifier. It could be put
after the var name, like this: ${FOO?} and signals that the var is
optional and can be evaluated to empty string.
Summary of the idea:
- when FOO is undefined
- ${FOO} evals to ${FOO} (unchanged behavior)
- ${FOO?} evals to empty string (new behavior)
- when FOO is set to bar
- ${FOO} evals to bar (unchanged behavior)
- ${FOO?} evals to bar (unchanged behavior)
—
Reply to this email directly, view it on GitHub
<#8335 (comment)>, or
unsubscribe
<https://github.com/notifications/unsubscribe-auth/A4Y2NHXKG6H4XCSKJJ7XAFT3BBFYBAVCNFSM6AAAAAB6EWCUAGVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDSMRSGI3TKMZVHE>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
|
Is there an existing issue for this?
This issue exists in the latest npm version
Current Behavior
If I add following line to
.npmrc
:it correctly works if the NODE_OPTIONS was set before to some node flags in my env. For example, if I do
then the Node being run by the "foo" script, receives
--inspect --use-system-ca
as node options and it's fine.But, if the
NODE_OPTIONS
env var is not set to anything when i donpm run foo
, then the Node receives${NODE_OPTIONS} --use-system-ca
as options and Node rejects all the options (--use-system-ca
is ignored as well).As a result of npm leaving var substitutions untouched if the var is not set, there is no way to reliably extend the node options via .npmrc instead of replacing them.
Expected Behavior
Either:
${FOO}
var substitution pattern should eval to empty string if FOO is not defined${FOO:-''}
can be used to just have an empty string if the var is not defined at allSteps To Reproduce
"foo": "node -e 'console.log(process.env.NODE_OPTIONS);'"
node-options = "${NODE_OPTIONS} --max-old-space-size=1"
NODE_OPTIONS='' npm run foo
- as expected the Node will fail to run because it runs out of the assigned 1mb of memory, meaning the flags were passed just fineunset NODE_OPTIONS
to make sure it is not set to any value, not even an empty stringnpm run foo
${NODE_OPTIONS} --max-old-space-size=1
printed and Node finishes just fine which means that the NODE_OPTIONS were ignored because of the incorrect string resulting from unsubstituted variableEnvironment
The text was updated successfully, but these errors were encountered: