Describe the bug
On Windows, when Node.js is installed in the default location (C:\Program Files\nodejs\node.exe — the standard path used by the official Windows installer), every command that shells out to npm (plugins:install, plugins:uninstall, plugins:update) fails with a misleading error:
CLIError: <package> does not exist in the registry.
This happens even for packages that genuinely exist and are installable via a normal npm view <package> in the same shell. The real failure has nothing to do with the registry — it's a broken subprocess spawn caused by the unescaped space in process.execPath.
Root cause
In lib/spawn.js, modulePath is set to process.execPath (added between 5.4.86 and 5.5.0), and the child process is spawned with windowsVerbatimArguments: true and no shell:
if (modulePath.endsWith('.js')) {
args.unshift(`"${modulePath}"`);
modulePath = process.execPath; // e.g. "C:\Program Files\nodejs\node.exe"
}
...
cpSpawn(modulePath, args, { cwd, env, stdio: 'pipe', windowsVerbatimArguments: true, ... })
Because windowsVerbatimArguments: true disables Node's automatic quoting of the executable path, and process.execPath contains a space (Program Files), Windows misparses the command line. Running with DEBUG=@oclif/plugin-plugins* shows the spawned process actually receives a garbled relative path:
node:internal/modules/cjs/loader:1503
throw err;
Error: Cannot find module 'C:\Users\<user>\AppData\Local\<cli>\Files\nodejs\node.exe'
i.e. the exe path got split at the space, and Files\nodejs\node.exe was passed as a relative script argument (resolved against the child's cwd). The npm subprocess exits with code 1, Plugins.npmHasPackage catches this and reports the package as not found in the registry — masking the real error.
Comparing with 5.4.86 (last known-good version), lib/spawn.js used the bare command name instead of the absolute exec path:
if (process.platform === 'win32' && modulePath.endsWith('.js')) {
args.unshift(`"${modulePath}"`);
modulePath = 'node'; // resolved via PATH, no spaces, no ambiguity
}
This avoided the issue entirely, since node (no path) has no spaces to misparse.
To Reproduce
- On Windows, with Node.js installed via the official installer (default path
C:\Program Files\nodejs\).
- Use any oclif CLI depending on
@oclif/plugin-plugins@^5.5.0.
- Run
DEBUG=@oclif/plugin-plugins* your-cli plugins:install <any-real-package>.
- Observe the CLIError
<package> does not exist in the registry., and in the debug output, the internal Cannot find module '...\Files\nodejs\node.exe' error from the spawned process.
Expected behavior
plugins:install/uninstall/update should work regardless of whether Node.js is installed under a path containing spaces.
Environment
- OS: Windows
@oclif/plugin-plugins: 5.5.0, 5.5.1 (regression); 5.4.86 (last known-good)
- Node.js: installed at default path
C:\Program Files\nodejs\node.exe
Suggested fix
Either revert to using the bare 'node' command (as in 5.4.86) on Windows, or properly quote modulePath before spawning, or drop windowsVerbatimArguments: true when the file path may contain spaces.
Describe the bug
On Windows, when Node.js is installed in the default location (
C:\Program Files\nodejs\node.exe— the standard path used by the official Windows installer), every command that shells out to npm (plugins:install,plugins:uninstall,plugins:update) fails with a misleading error:This happens even for packages that genuinely exist and are installable via a normal
npm view <package>in the same shell. The real failure has nothing to do with the registry — it's a broken subprocess spawn caused by the unescaped space inprocess.execPath.Root cause
In
lib/spawn.js,modulePathis set toprocess.execPath(added between 5.4.86 and 5.5.0), and the child process is spawned withwindowsVerbatimArguments: trueand no shell:Because
windowsVerbatimArguments: truedisables Node's automatic quoting of the executable path, andprocess.execPathcontains a space (Program Files), Windows misparses the command line. Running withDEBUG=@oclif/plugin-plugins*shows the spawned process actually receives a garbled relative path:i.e. the exe path got split at the space, and
Files\nodejs\node.exewas passed as a relative script argument (resolved against the child'scwd). The npm subprocess exits with code 1,Plugins.npmHasPackagecatches this and reports the package as not found in the registry — masking the real error.Comparing with 5.4.86 (last known-good version),
lib/spawn.jsused the bare command name instead of the absolute exec path:This avoided the issue entirely, since
node(no path) has no spaces to misparse.To Reproduce
C:\Program Files\nodejs\).@oclif/plugin-plugins@^5.5.0.DEBUG=@oclif/plugin-plugins* your-cli plugins:install <any-real-package>.<package> does not exist in the registry., and in the debug output, the internalCannot find module '...\Files\nodejs\node.exe'error from the spawned process.Expected behavior
plugins:install/uninstall/updateshould work regardless of whether Node.js is installed under a path containing spaces.Environment
@oclif/plugin-plugins: 5.5.0, 5.5.1 (regression); 5.4.86 (last known-good)C:\Program Files\nodejs\node.exeSuggested fix
Either revert to using the bare
'node'command (as in 5.4.86) on Windows, or properly quotemodulePathbefore spawning, or dropwindowsVerbatimArguments: truewhen the file path may contain spaces.