On Windows cmd.exe, NODE_NO_WARNINGS=1 node app.js fails with 'NODE_NO_WARNINGS' is not recognized as an internal or external command because cmd has no Unix-style inline env-var prefix — it parses the assignment as the command name and tries to execute it. The same root cause hits NODE_ENV=production node app.js and NODE_OPTIONS=--max-old-space-size=4096 node app.js: fix one and you understand all of them. Since Node.js 21.3.0 (December 2023), the --disable-warning=<code> flag is a more precise fix than the blanket NODE_NO_WARNINGS envelope, and on Node 22+ the most-cited offender — the require(ESM) experimental warning — does not fire anymore at all.
TL;DR
- Cause: Unix inline env-var syntax (
FOO=bar cmd) does not exist incmd.exe. - Quick fix (cmd):
set NODE_NO_WARNINGS=1 && node app.js— no space before&&or the variable picks up trailing whitespace. - Quick fix (PowerShell):
$env:NODE_NO_WARNINGS=1; node app.js. - Cross-platform npm scripts:
npx cross-env NODE_NO_WARNINGS=1 node app.js, or usenode --no-warnings app.jsdirectly. - Better than a blanket mute:
node --disable-warning=DEP0040 app.jssilences only the punycode deprecation and keeps everything else visible.
Why does 'NODE_NO_WARNINGS' is not recognized happen on Windows?
Bash, zsh, and other POSIX shells treat VAR=value command as a single statement: they export VAR into the environment of command for that one invocation and then unset it. Windows cmd.exe has no such grammar. When you type NODE_NO_WARNINGS=1 node app.js, cmd takes the first whitespace-delimited token as the program name, looks for NODE_NO_WARNINGS=1.exe (and .bat, .cmd, etc.) on PATH, finds nothing, and prints the recognised error.
The same applies to every Node env-var prefix copy-pasted from a Linux tutorial: NODE_ENV=production node app.js, NODE_OPTIONS=--no-warnings node app.js, DEBUG=express:* node app.js. The error is a shell issue, not a Node issue — Node never gets a chance to run. PowerShell and Git Bash behave differently again, which is why a script that works in one Windows terminal can fail in another.
How do you fix it in Windows cmd.exe?
Set the variable first, then run Node. Two reliable patterns:
REM One-liner: && chains in cmd. Watch the spaces.
set NODE_NO_WARNINGS=1 && node app.js
REM Pitfall: "set NODE_NO_WARNINGS=1&& node app.js" (no spaces) works.
REM But "set NODE_NO_WARNINGS=1 && node app.js" with a space before &&
REM gives NODE_NO_WARNINGS the value "1 " (with trailing space).
REM Node accepts it for boolean flags, but breaks numeric values.
REM Two-liner: clearer, and the variable persists for this cmd session.
set NODE_NO_WARNINGS=1
node app.jsFor values that should survive across cmd sessions, use setx instead of set — but note that setx writes to the user registry and the new value only appears in new shells. The current cmd window keeps the old value until you close it.
How do you fix it in PowerShell?
PowerShell exposes process environment variables under the $env: drive. The semicolon separates statements:
# Set for this process invocation only.
$env:NODE_NO_WARNINGS=1; node app.js
# Set for the whole PowerShell session.
$env:NODE_NO_WARNINGS = 1
node app.js
# Persist for the current user (survives reboots; new shells inherit it).
[Environment]::SetEnvironmentVariable('NODE_NO_WARNINGS', '1', 'User')Git Bash and WSL bash on Windows use the POSIX grammar, so the Linux one-liner NODE_NO_WARNINGS=1 node app.js works there unchanged. If you are bouncing between terminals on one machine, see the sibling Docker on Windows guide for the WSL2 vs native-Windows shell breakdown that applies to Node the same way.
How do you fix it cross-platform in npm scripts?
npm does not rewrite Unix env-var prefix syntax. It hands the script string to the OS shell — cmd on Windows, sh on Linux and macOS — so an npm script that works locally on a Mac will break on a Windows teammate's machine with the exact same error. The standard fix is cross-env, which exports the variable in a shell-neutral way before invoking the next command:
{
"scripts": {
// Breaks on Windows cmd:
"start": "NODE_NO_WARNINGS=1 node app.js",
// Works everywhere:
"start": "cross-env NODE_NO_WARNINGS=1 node app.js",
// Or skip the env var entirely:
"start": "node --no-warnings app.js"
}
}cross-env 8.x requires Node ≥ 20; pin cross-env@7 if you still ship anything for Node 18 or older. On GitHub Actions Windows runners, the cleanest workaround is shell: bash on the step — the bundled Git Bash gives you Unix semantics and the prefix syntax works as-is. For deeper coverage of env-var loading, validation, and Node 20.6+ --env-file, see the Node.js env variables guide.
Should you use --no-warnings or --disable-warning instead?
For any real codebase, yes — pass flags to node directly instead of going through an environment variable. Three options, in order of precision:
| Mechanism | What it silences | Available since |
|---|---|---|
| node --disable-warning=DEP0040 | One specific warning code or type (e.g. DEP0040, DeprecationWarning). | Node 21.3.0 |
| node --no-warnings | All process warnings, equivalent to NODE_NO_WARNINGS but flag-shaped. | Node 6.0.0 |
| NODE_NO_WARNINGS=1 | All process warnings; needs shell-specific syntax on Windows. | Node 7.0.0 |
NODE_OPTIONS is the alternative when you cannot edit the invocation — for example, when Node is launched by a tool like npm test, turbo, or a CI runner. Set NODE_OPTIONS=--no-warnings (or --disable-warning=DEP0040) the same way you would set any other Windows env var. Multiple flags must be space-separated inside one value — Node merges nothing across multiple NODE_OPTIONS assignments.
What does NODE_NO_WARNINGS actually suppress?
Anything emitted via Node's process.emitWarning() — the same channel the runtime uses for deprecations and experimental flags. That covers:
- DeprecationWarning — APIs scheduled for removal (e.g. DEP0040 for
node:punycode). - ExperimentalWarning — features still behind
--experimental-*flags. - PendingDeprecationWarning — only when
--pending-deprecationis also set. - Library warnings — anything Mongoose, dotenv, AWS SDK, etc. push through
process.emitWarning().
It does not suppress: thrown errors, console.warn output, V8 or OpenSSL messages written to stderr directly, or loader errors from tsx / ts-node. If your noisy output survives NODE_NO_WARNINGS=1, it is one of those.
Which warning are you actually trying to silence in 2026?
Before muting everything, check what is firing. Run node --trace-warnings app.js once to see the warning code and the emitting stack frame. Most 2026 cases fall into a small set:
| Warning | Common trigger | Targeted fix |
|---|---|---|
| DEP0040 | node:punycode pulled in transitively by uri-js, tough-cookie, older Yarn versions. | --disable-warning=DEP0040 |
| DEP0190 | Passing a single string to child_process.execSync with shell: true as the only option. | --disable-warning=DEP0190 |
| ExperimentalWarning | --experimental-strip-types, --experimental-vm-modules, custom loaders via --experimental-loader (deprecated in favour of --import). | --disable-warning=ExperimentalWarning |
| (no warning) | fetch() ExperimentalWarning, and require(ESM) ExperimentalWarning. | Gone in Node 21+ and Node 22.12 / 20.19 respectively. If a 2017–2023 Stack Overflow answer tells you to silence these, your Node is current and the warning is not being emitted anymore. |
require(ESM) reached stable in Node 22.12.0 (December 2024) and was backported to 20.19 — the warning that drove most NODE_NO_WARNINGS Google searches between 2023 and early 2025 stopped firing across the entire active LTS line.
When should you not suppress Node warnings?
- In CI. Silencing in
npm testorturbo run buildhides the next deprecation from your team. Let CI surface them; mute selectively with--disable-warning=<code>only after you have triaged. - In published libraries. Never set
NODE_NO_WARNINGS=1inside a package'sprepareorpostinstall— you suppress warnings for every consumer. Library code should fix the deprecation, not hide it. - During a migration window. If you are halfway through removing a deprecated API, prefer the targeted
--disable-warning=<code>so new, unrelated warnings still appear and you spot regressions early. - When the noise is not a warning.
console.warncalls and direct stderr writes ignoreNODE_NO_WARNINGSentirely — silencing it does nothing and you have masked a different problem.
Frequently Asked Questions
Why does 'NODE_NO_WARNINGS' is not recognized happen on Windows?
cmd.exe has no Unix-style inline env-var grammar. When you type NODE_NO_WARNINGS=1 node app.js, cmd treats NODE_NO_WARNINGS=1 as the program name, looks it up on PATH, finds nothing, and prints the not-recognised error. The same applies to NODE_ENV, NODE_OPTIONS, DEBUG, and any other prefix copy-pasted from a Linux tutorial.
What's the cmd.exe equivalent of NODE_NO_WARNINGS=1 node app.js?
Use two statements joined with &&: set NODE_NO_WARNINGS=1 && node app.js. Mind the spaces — if you write "set NODE_NO_WARNINGS=1 && node app.js" with a space before &&, the variable picks up trailing whitespace. Either omit the space ("set NODE_NO_WARNINGS=1&& node app.js") or split onto two lines.
How do I set NODE_NO_WARNINGS in PowerShell?
Use the $env: drive: $env:NODE_NO_WARNINGS=1; node app.js. For the whole session, set $env:NODE_NO_WARNINGS = 1 on its own line. To persist across reboots: [Environment]::SetEnvironmentVariable('NODE_NO_WARNINGS', '1', 'User').
Should I use NODE_NO_WARNINGS or --disable-warning=DEP0040 for the punycode warning?
Use --disable-warning=DEP0040 (Node 21.3.0+). NODE_NO_WARNINGS silences every process warning including future deprecations you actually want to see. --disable-warning targets just the one code, so the next unrelated deprecation still surfaces. The flag form also avoids the Windows shell-quoting problem entirely.
Why does my npm script work on macOS but break on Windows with the same error?
npm does not rewrite Unix env-var prefix syntax. It passes the script string to the OS shell — sh on macOS/Linux (where FOO=bar cmd works), cmd on Windows (where it does not). Fix it with cross-env: "start": "cross-env NODE_NO_WARNINGS=1 node app.js". Or sidestep the env var with "start": "node --no-warnings app.js".
References
- Node.js CLI — NODE_NO_WARNINGS, --no-warnings, --disable-warning — canonical reference for every warning-suppression mechanism and which versions added them.
- Node.js 21.3.0 release notes — introduction of
--disable-warning=<code|type>for targeted suppression. - Node.js 22.12.0 release notes — require(ESM) unflagged, ending the most-cited reason developers reached for
NODE_NO_WARNINGSin 2023–2024. - nodejs/node#10802 — original feature request that added
NODE_NO_WARNINGSin Node 7. - cross-env on npm — the standard shim for setting env vars in npm scripts that run on Windows and Unix without modification.
- Apache Arrow ARROW-7114 — real-world Windows CI reproduction of the same shell-grammar issue, fixed by switching to
cross-env.