Skip to content
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

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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant