Skip to content

Conversation

@SongMinQQ
Copy link

@SongMinQQ SongMinQQ commented Apr 2, 2025

This pull request addresses a bug in the npm run-script chain on Windows when running commands such as npm start in a React project under Node.js 22.14.0 LTS.

In our environment, the environment variable process.env.ComSpec—which is typically used to determine the default shell (e.g., "C:\Windows\System32\cmd.exe")—is missing.

As a result, the code in the spawnWithShell function falls back to an undefined value for the shell command.

This causes the subsequent call to child_process.spawn() to receive undefined as the file argument, leading to the error:

The "file" argument must be of type string. Received undefined

13 verbose stack TypeError [ERR_INVALID_ARG_TYPE]: The "file" argument must be of type string. Received undefined
13 verbose stack     at normalizeSpawnArguments (node:child_process:539:3)
13 verbose stack     at spawn (node:child_process:746:13)

The fix implemented in this PR adds a fallback so that if process.env.ComSpec is not defined, it defaults to using "cmd.exe". This ensures that the command is properly resolved and that the shell execution chain works as expected.

Changes made:

  • In the spawnWithShell function, the code is modified as follows:
    if (command === true) {
      // Use the default shell: if process.env.ComSpec is missing, fallback to 'cmd.exe'
      command = process.platform === 'win32' ? (process.env.ComSpec || 'cmd.exe') : 'sh';
    }
    

References

@wraithgar
Copy link
Member

this code is in https://github.com/npm/promise-spawn, it's included in the node_modules here cause npm vendors its dependencies so it works out of the box.

@wraithgar wraithgar closed this Apr 2, 2025
owlstronaut pushed a commit to npm/promise-spawn that referenced this pull request Aug 28, 2025
### What / Why
---

issue No. #131 

On Windows, some environments don’t expose process.env.ComSpec.
When that happens, the shell selection logic ends up passing undefined
to child_process.spawn(), throwing ERR_INVALID_ARG_TYPE (“file” must be
a string).

This PR updates the shell resolution so that on win32 we fallback to
"cmd.exe" when process.env.ComSpec is missing, while preserving existing
behavior on:

non-Windows (sh) and

Windows when ComSpec is set (still honored).

Rationale: cmd.exe is the standard Windows shell and is present by
default. This change prevents crashes in real-world setups without
altering behavior for users who explicitly define ComSpec.

### Change summary

Update shell selection:

```
command = process.platform === 'win32'
  ? (process.env.ComSpec || 'cmd.exe')
  : 'sh'
```

Add/adjust tests to cover the “missing ComSpec” case on Windows.

### Tests

```
os: Windows 10 (WSL2)
node: 22.14.0
npm: 11.2.0
```

<img width="662" height="495" alt="image"
src="https://github.com/user-attachments/assets/48578508-f3e5-41b2-8712-3afbb220a743"
/>

### References

Prior attempt on npm/cli was closed with a maintainer note that this
logic lives in @npmcli/promise-spawn (npm vendors this dependency).
[GitHub](npm/cli#8205)
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 this pull request may close these issues.

2 participants