volta
volta copied to clipboard
Volta breaks with `child_process.exec` in `cmd` (Windows)
As reported in this SO thread:
Results
Given below code, I get the following results:
| cmd | Result | |
|---|---|---|
| ❌ | '"yarn" -v' |
Cannot find module 'C:\cwd\yarn.js' |
| ❌ | '"npm" -v' |
Cannot find module 'C:\cwd\node_modules\npm\bin\npm-cli.js' |
| ✅ | 'yarn -v' |
(works as expected) |
| ✅ | '"C:/Program Files/Volta/yarn" -v' |
(works as expected) |
OS: Win10
Node: v16.*, v17.* (tried several of them)
shell: cmd (NOTE: If I set processOptions.shell = 'bash', it works fine)
Full Error Message
node:internal/modules/cjs/loader:936
throw err;
^
Cannot find module 'C:\cwd\node_modules\npm\bin\npm-cli.js'
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47 {
code: 'MODULE_NOT_FOUND',
requireStack: []
}
Done - code 1 signal null
Code
// test.js
const cp = require('child_process');
const cmd = 'echo hi && "yarn" install';
const child = cp.exec(cmd);
// ###########################################################################
// process monitoring
// ###########################################################################
child.on('exit', (code, signal) => {
console.log('Done - code', code, ' signal', signal);
});
child.on('error', (err) => {
console.error(`Error:`, err);
});
// inherit stdio
child.stdout.pipe(process.stdout);
process.stdin.pipe(child.stdin);
child.stderr.pipe(process.stderr);
This happens only with yarn and npm. Everything else (thus far) seems fine, including node itself.
Hi @Domiii, that's very strange! In your examples / error, is cwd actually a literal that's printed, or is that eliding the actual CWD for the process?
While Volta's shims being native binaries, they can definitely confuse things in edge cases (see #1032 for an example where the extra indirection breaks IPC), once we launch Node, Volta doesn't have any more active involvement. And the PATH for that process should be set up to include Node, npm, and Yarn directly, exactly as it would work for any other version manager (or if you didn't have a version manager at all).
It feels like something is trying to locate the npm or yarn script files relative to the current directory, rather than relative to the directory where the executables themselves are located. The fact that it only happens with shell: cmd and not with other shells also makes me suspicious that it's some strange interaction with cmd.exe and its highly non-standard executable handling.
How exactly are you executing the above code? Can you try adding a console.log(process.env.PATH) (might be process.env.Path on Windows, since the casing is different for the environment variable name) to the script to inspect what the PATH looks like when it's executing?
hi @charlespierce,
-
highly non-standard executable handling
- Evidently, someone does not like those double quotation marks, and because of that, possibly assumes that
"yarn"is an absolute, rather than a relative path? - It could be anywhere, maybe even node's
child_process? - Can you point me to a
Volta*.js file (installed on my system) that I can edit to print out some info as to how it is invoked and how it tries to look-up the target path?
- Evidently, someone does not like those double quotation marks, and because of that, possibly assumes that
-
is cwd actually a literal that's printed, or is that eliding the actual CWD for the process?
- Its the actual
cwd, omitted here since the folder structure does not matter. It also does not change if I execute it in different folders.
- Its the actual
-
It feels like something is trying to locate the npm or yarn script files relative to the current directory, rather than relative to the directory where the executables themselves are located.
- It certainly looks that way!
-
How exactly are you executing the above code?
node <path-to-script>(does not matter if absolute or relative path, always observes the same behavior)
-
Can you try adding a
console.log(process.env.PATH)C:\Users\domin\AppData\Local\Volta\tools\image\yarn\1.22.17\bin C:\Users\domin\AppData\Local\Volta\tools\image\node\16.14.2 C:\Program Files\Volta\ C:\Program Files (x86)\Common Files\Oracle\Java\javapath C:\Python39\Scripts\ C:\Python39\ C:\Windows\system32 C:\Windows C:\Windows\System32\Wbem C:\Windows\System32\WindowsPowerShell\v1.0\ C:\Windows\System32\OpenSSH\ C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common C:\Program Files\NVIDIA Corporation\NVIDIA NvDLISR C:\ProgramData\chocolatey\bin C:\Program Files\Git\cmd C:\Program Files\Git\mingw64\bin C:\Program Files\Git\usr\bin C:\texlive\2021\bin\win32 C:\Users\user\AppData\Local\Volta\bin C:\Users\user\AppData\Local\Microsoft\WindowsApps C:\Users\user\AppData\Local\Programs\Microsoft VS Code\bin C:\Users\user\AppData\Roaming\Python\Python39\Scripts
Wow, that's very odd. The Path looks correct (having the resolved versions first), so I don't think it's that. My best guess is that this is somehow related to cmd.exe, which definitely has some strange behavior around quoting (including a /s flag that causes it to use even different behavior).
Can you point me to a Volta *.js file (installed on my system) that I can edit to print out some info as to how it is invoked and how it tries to look-up the target path?
Volta is a native binary, so no JS files to edit in place, unfortunately. You can find the underlying yarn scripts by looking at the above Path entry, however: C:\Users\<username>\AppData\Local\Volta\tools\image\yarn\<version>\bin should have the actual scripts that get executed when you run yarn (though those may be thin wrappers that direct somewhere else).
Its the actual
cwd, omitted here since the folder structure does not matter. It also does not change if I execute it in different folders.
When you say it doesn't change if you execute it in different folders, do you mean the absolute path remains the same, even if it's being run from different places? In that case, does the folder structure include the Volta directory (e.g. is it like the above Path entry with AppData\Local\Volta\tools\image in there? Or do you just mean that the rest of the path is consistent, with the only change being due to a change in the current directory?
When you say it doesn't change if you execute it in different folders Sorry for being inaccurate: I mean, it is still the corresponding
cwd(i.e. your last guess: "Or do you just mean that the rest of the path is consistent, with the only change being due to a change in the current directory?"). So the foolder changes as expected, but (I guess what I meant was) the behavior is what did not change.
Have you tried this yourself? I'll see if I can repro on another Windows computer. But for now it appears a problem that should be reproducable anywhere, at the intersection of:
Windows + cmd + child_process + double-quotes.
The problem does not appear if any of these elements is removed.
I imagine this is the same underlying cause as #1010, which is cmd.exe having documented strange behaviour with regards to quotes and spaces.