Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Incompatible with Windows Node 20.12.2 #1453

Closed
longzheng opened this issue Apr 29, 2024 · 1 comment · Fixed by #1455
Closed

Incompatible with Windows Node 20.12.2 #1453

longzheng opened this issue Apr 29, 2024 · 1 comment · Fixed by #1455

Comments

@longzheng
Copy link
Contributor

longzheng commented Apr 29, 2024

Describe the bug

I know technically Scrypted's Windows install script hard-codes the Node version to 20.11.1 so any higher version is unsupported, but I thought I'd document this bug with Node v20.12.2 in case anyone manually updates their Node.js version like me.

I noticed that the Scrypted service was not starting.

I tried running the service manually with node %USERPROFILE%\.scrypted\service.js and got the following exception

Microsoft Windows [Version 10.0.22631.3447]
(c) Microsoft Corporation. All rights reserved.

C:\Users\Long>node %USERPROFILE%\.scrypted\service.js
node:internal/child_process:421
    throw new ErrnoException(err, 'spawn');
    ^

Error: spawn EINVAL
    at ChildProcess.spawn (node:internal/child_process:421:11)
    at Object.spawn (node:child_process:761:9)
    at Object.<anonymous> (C:\Users\Long\.scrypted\service.js:8:15)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10)
    at Module.load (node:internal/modules/cjs/loader:1206:32)
    at Module._load (node:internal/modules/cjs/loader:1022:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:135:12)
    at node:internal/main/run_main_module:28:49 {
  errno: -4071,
  code: 'EINVAL',
  syscall: 'spawn'
}

Node.js v20.12.2

After a quick Google, I found other people documenting the same error code which is the result of a security behaviour change in 20.12.2 specifically for Windows.

It is important to note that there has been a breaking change for Windows users who utilize child_process.spawn and child_process.spawnSync. Node.js will now error with EINVAL if a .bat or .cmd file is passed to child_process.spawn and child_process.spawnSync without the shell option set. If the input to spawn/spawnSync is sanitized, users can now pass { shell: true } as an option to prevent the occurrence of EINVALs errors.

Of course Scrypted's service.js tries to launch npx.cmd which is affected.

I tried modifying service.js to include shell: true

child_process.spawn('C:\\Program Files\\nodejs\\npx.cmd', ['-y', 'scrypted', 'serve'], {
    stdio: 'inherit',
    shell: true,
});

but this led to a different error

node %USERPROFILE%\.scrypted\service.js
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.

Turns out shell: true changes the behaviour of spaces in spawn nodejs/node#7367. The fix is to wrap the whole string in a double quote.

child_process.spawn('"C:\\Program Files\\nodejs\\npx.cmd"', ['-y', 'scrypted', 'serve'], {
    stdio: 'inherit',
    shell: true,
});

It now launches, but then runs into more spawn EINVAL errors.

node %USERPROFILE%\.scrypted\service.js
cwd C:\Users\Long\.scrypted
Starting scrypted main...
running npm.cmd --prefix C:\Users\Long\.scrypted exec scrypted-serve
scrypted server exited with error Error: spawn EINVAL
    at ChildProcess.spawn (node:internal/child_process:421:11)
    at Object.spawn (node:child_process:761:9)
    at runCommand (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\service.js:22:40)
    at runServer (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\service.js:44:11)
    at startServer (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\service.js:49:15)
    at serveMain (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\service.js:125:15)
    at main (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\main.js:114:39)
    at Object.<anonymous> (C:\Users\Long\AppData\Local\npm-cache\_npx\f8ff587849d254b8\node_modules\scrypted\dist\packages\cli\src\main.js:221:1)
    at Module._compile (node:internal/modules/cjs/loader:1369:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1427:10) {
  errno: -4071,
  code: 'EINVAL',
  syscall: 'spawn'
}
Service unexpectedly exited. Restarting momentarily.

This appears to be because of

if (os.platform() === 'win32')
command += '.cmd';
console.log('running', command, ...args);
const cp = child_process.spawn(command, args, {

If I add shell: true to this it seems to work.

@longzheng
Copy link
Contributor Author

I'll try open a PR to fix this.

@longzheng longzheng changed the title Incompatible with Windows Node 20..12.2 Incompatible with Windows Node 20.12.2 Apr 29, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant