Repository navigation
With "type": "commonjs", #!/usr/bin/env node file does not execute but returns success and no error messages when the file is ESM #61104
Copy link
Copy link
Closed
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.loadersIssues and PRs related to ES module loaders.Issues and PRs related to ES module loaders.
Description
Activity
- changed the title
[-]`#!/usr/bin/env node` file does not execute but returns success and no error messages when the file is ESM[/-][+]With `"type": "commonjs"`, `#!/usr/bin/env node` file does not execute but returns success and no error messages when the file is ESM[/+]on Dec 18, 2025 I'm able to reproduce on
mainand up to 20.19.6 with the following:mkdir repro && {( cd repro echo '{ "type": "commonjs" }' > package.json printf '#!/usr/bin/env node\nprocess.exitCode=42;export {}\n' > script chmod +x script NODE_DEBUG=* ./script echo "Exit code was $?" ) rm -rf repro }
The output is
MODULE 72559: looking for "…/repro/script" in […] MODULE 72559: load "…/repro/script" for module "." MODULE_TIMER 72559 [] […/repro/script]: 6.926ms ESM 72559: Translating CJSModule file://…/repro/script ESM 72559: Preparsing exports of …/repro/script ESM 72559: Storing file://…/repro/script (implicit type) in ModuleLoadMap ESM 72559: ModuleJob.run() ModuleWrap { url: 'file://…/repro/script', [Symbol(imported_cjs_symbol)]: { id: '.', path: '…/repro', exports: {}, filename: '…/repro/script', loaded: true, children: [], paths: [ '…/repro/node_modules', '…/node_modules', … ], [Symbol(kIsMainSymbol)]: true, [Symbol(kIsCachedByESMLoader)]: false, [Symbol(kURL)]: undefined, [Symbol(kFormat)]: undefined } } ESM 72559: async addJobsToDependencyGraph() file://…/repro/script ModuleJob { importAttributes: [Object: null prototype] {}, isMain: true, inspectBrk: false, url: 'file://…/repro/script', module: ModuleWrap { url: 'file://…/repro/script', [Symbol(imported_cjs_symbol)]: { id: '.', path: '…/repro', exports: {}, filename: '…/repro/script', loaded: true, children: [], paths: [Array], [Symbol(kIsMainSymbol)]: true, [Symbol(kIsCachedByESMLoader)]: false, [Symbol(kURL)]: undefined, [Symbol(kFormat)]: undefined } }, modulePromise: Promise { ModuleWrap { url: 'file://…/repro/script', [Symbol(imported_cjs_symbol)]: [Object] } }, linked: Promise { <pending> }, instantiated: undefined } ESM 72559: Loading CJSModule file://…/repro/script Exit code was 0Reacted by Lucas Fernando Cardoso Nunes- addedconfirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.
on Dec 18, 2025 /cc @nodejs/loaders
- addedloadersIssues and PRs related to ES module loaders.Issues and PRs related to ES module loaders.
on Dec 30, 2025 - added a commit that references this issue
on Jan 5, 2026 - added a commit that references this issue
on Feb 8, 2026 - added a commit that references this issue
on Feb 16, 2026 - added a commit that references this issue
on Feb 19, 2026 - added 2 commits that reference this issue
on Mar 9, 2026 - added a commit that references this issue
on Mar 10, 2026 6f4a4f6- [ ] ef4c3
Metadata
Metadata
Assignees
Labels
confirmed-bugIssues and PRs for confirmed bugs.Issues and PRs for confirmed bugs.loadersIssues and PRs related to ES module loaders.Issues and PRs related to ES module loaders.
Version
v24.11.1
Platform
Subsystem
No response
What steps will reproduce the bug?
Create a
package.jsoncontaining only{}. Create the following filescriptand chmod it executable. (Note that it's ESM, not CommonJS.)In that same directory, run the script and observe that it produces the expected output and "success" exit code:
Now add to your
package.jsonthe line"type": "commonjs". Run the script again, and note that it produces no output at all (neither what it is expected to print nor any errors), and yet still exits with exit code 0, indicating success:If you feel like it, you can replace the ESM import with
const { version } = require('node:process')and see that it does work as in the first example run above.How often does it reproduce? Is there a required condition?
Always reproduces.
What is the expected behavior? Why is that the expected behavior?
I expect the
"type": "commonjs"case to do two things, in order of importance:Exit with a non-zero exit code (indicating "failure") because it didn't run. This would help avoid the especially insidious situation where it's a script running in a build system that's expected to do something important but produce no output. (Ask me how I know this is "insidious." :-))
Print some sort of error to stderr indicating that the script can't be run, ideally including some information about the configuration that's preventing this. (In this case, I guess, it's that the auto-detection of ESM vs. CommonJS based on file contents is disabled due to the
"type": "commonjs"inpackage.json?)What do you see instead?
See output in reproduction above.
Additional information
node --print-all-exceptions ./script >exceptions.txt 2>&1may have some useful information in its 1240 lines. I've attached the output from my machine asexceptions.txt.Also, possibly #49444 "Feature: ESM in executable files" may have some relation to this, though I've not read through it carefully (it's a long read).