-
Notifications
You must be signed in to change notification settings - Fork 104
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
Please add switch to opt-out of special ENOENT behavior for Windows if desired #104
Comments
@mattflix are you willing to do a PR to add such an feature via an option named |
I just wanted to express a big thanks to @mattflix for describing this issue so well. I am also running into a problem that could be solved by an option for disabling the I don't want to volunteer to fix this, because I don't have a Windows machine handy, nor do I have the interest in understanding this issue any more intimately. I have a workaround that I think is good enough for now. I just wanted to make the community aware of this usage and the need. |
@satazor, I could take a stab at it. I see the modifications needed in I have some concerns/questions:
Any thoughts or advice? |
Sorry for the late answer, I'm reading all the issues again and I would like to refresh this one.
Correct, that's why there's a check in place to also see if the actual command file exists and only throw ENOENT if it doesn't.
This module is not designed to call
This shouldn't happen as this module should have detect I would like to replicate the issue to understand if we could improve the |
Thanks for the reply.
It is not PowerShell cmdlets specifically that are "the issue" here, but rather Not to get off track, but keep in mind there may be many legitimate ways to use cmdlets as part of an overall cross-platform solution (of which
Not sure if anything is {
"name": "enoent",
"version": "1.0.0",
"dependencies": {
"cross-env": "^5.2.0",
"mocha": "^6.0.2"
},
"config": {
"tests": "--ui exports test.js"
},
"scripts": {
"mocha": "cross-env-shell mocha $npm_package_config_tests",
"premocha": "node -e \"console.log(\\\"module.exports = { test() { throw new Error } }\\\")\" > test.js"
}
} This repros basically the exact issue (though greatly simplified) I had running Anyway, to repro, place the above text in a file named (Btw, the On Mac, On Windows, you get the In this repo case, obviously IMO, Of course, if the shim can be fixed to just "always do the right thing", that would be great too... but I don't think that is realistically possible.
Hopefully the above repro will give you something to go on. |
+1 on everything @mattflix said. I think the
This is not true. The only way to spot I.e. the Example to reproduce the issue (on Windows):
throw new Error('This error message and stack trace will never be shown') In Node: const crossSpawn = require('cross-spawn')
const childProcess = crossSpawn('node', ['test.js'], {shell: true})
childProcess.on('exit', (exitCode, signal) => {
console.log({ exitCode, signal })
})
childProcess.on('error', (error) => {
console.log(error)
} Prints:
If you're ok with removing the logic altogether, I can submit a PR. |
Is there a fix to this issue? |
This bug was mentioned in sindresorhus/execa#446 @satazor If you think my above comment is a good solution, please let me know and I will submit a PR. Thanks! |
Some additional information to add to this issue: Node.js actually implements some logic to detect Going back to the original issue which created the feature we are discussing, the problem is than However, libuv has access to the Windows API system error codes while |
I just like to leave my +1 here. I ran into this and it took me a day to understand why my command had the full expected output in I'm working on a Electron app that uses NPM cli to run some commands, including the I'm not too familiar with spawn and only recently started to use it so for sure this played a role on the time it took for me to debug this, but I bet this isn't the only case out there form cli tools where exit code Thanks for making |
In my use of
cross-spawn
(actually via thecross-env
package), I have discovered that there is some special error-emission behavior (apparently for Windows andcmd.exe
?) implemented by theenoent.js
source file, which is described on the following line:https://github.com/moxystudio/node-cross-spawn/blob/master/lib/enoent.js#L25
This line also contains a comment which refers the original issue.
Basically, the special behavior is: If the spawned process exits with 1 and the command line cannot be found in file system, emit an
Error
describing anENOENT
error condition (i.e., "command not found").(It may be helpful to familiarize yourself with the source code and the details of the original issue before reading on.)
But, there is (and IMO has always been) a problem: The logic in
enoent.js
assumes that exit code 1 should aways trigger the specialENOENT
error-emission behavior... but the assumptions behind that special behavior are only correct in certain cases, wrong in others.Firstly,
cmd.exe
may not even be in the picture, so any behavior based on the assumption that it is, is flawed. (Windows has a new shell, now the default, calledPowerShell.exe
, so the chances thatcmd.exe
is not being used is actually quite high.)Secondly, there are many used-cases in which an exit code of 1 does not implicitly mean "command not found". Even with
cmd.exe
this could easily be the case... any Windows command script, or process launched by the script, could simply choose to exit the script with 1, or any other code, for any purpose.Thirdly, the command passed to
cross-spawn
may not be an actual file-system location that can be "verified" exists or not. This is especially true with PowerShell, since the command might refer to a "cmdlet" (callable entities which are named independently of the file system) that ran successfully, but simply chose to exit with 1.In short, this special hard-coded behavior can easily do the wrong thing. For some cases, it may be desirable to convert exit code 1 + "command not found" into an emission of
ENOENT
, but in other cases, this logic is wrong, and only creates confusion and annoyance.Case in point: Unit test frameworks (
mocha
for example) exit with the number of failed tests (i.e., 0 for success, any other number for failure). Whencross-spawn
is used in such a case, a confusingENOENT
error occurs whenever 1 test fails, but not when 2 more tests fail.For real-world cases like this, where the special
ENOENT
behavior is not appropriate, would you consider adding a flag to allow the caller to opt-out of the special logic? That is, just pass any exit code straight through. (Better yet, IMO, place the current special behavior behind an opt-in flag instead.)Thanks.
The text was updated successfully, but these errors were encountered: