The npm "spawn ENOENT" error means Node.js could not find an executable that an npm script tried to launch. Usually the command is missing from PATH or node_modules is broken.
The "spawn ENOENT" error occurs when Node.js attempts to launch a command via `child_process.spawn()` but cannot locate the specified executable. ENOENT is a standard POSIX error code meaning "No such file or directory." When you run npm scripts, npm uses Node.js's child_process module to spawn the commands in your `package.json` "scripts" (and lifecycle hooks like `preinstall`/`postinstall`). If the program being launched (such as `git`, `python`, `bash`, or a package's binary) cannot be found on your system's PATH — or the working directory passed to spawn does not exist — Node.js throws this error. The message frequently does not say which command failed, which makes it hard to debug. This error is especially common on Windows, where executable resolution differs from Unix: `spawn` does not consult PATHEXT or run through a shell by default, so launching `.cmd`/`.bat` shims (which is how many Node CLIs are installed on Windows) fails unless a shell is used. It is also common in CI/CD pipelines and slim Docker images where expected tools or shells are simply not installed.
The error message often does not show which command failed. Re-run npm with verbose logging using the correct flag (--loglevel verbose, or its alias -d):
npm install --loglevel verbose
# or for a script
npm run your-script --loglevel verboseScan the output for the failing command name near the spawn ENOENT line. You can also turn on npm's internal debug logging:
# Linux/macOS
NPM_CONFIG_LOGLEVEL=silly npm install
# Windows PowerShell
$env:NPM_CONFIG_LOGLEVEL="silly"; npm installThen open the package.json "scripts" section and check which command might be unavailable on your system. The npm debug log at the path printed in the error (e.g. ~/.npm/_logs/...-debug-0.log) also records the exact command.
Once you know which command is failing, confirm it is installed and on PATH:
# Linux/macOS
which git
which python3
# Windows Command Prompt
where git
where python
# Windows PowerShell
Get-Command git
Get-Command pythonIf it is not found, install it:
# macOS (Homebrew)
brew install git python
# Ubuntu/Debian
sudo apt-get install git python3
# Windows (Chocolatey)
choco install git pythonOpen a new terminal afterward so the updated PATH is loaded.
On Windows, a missing PATH entry is a common cause. Verify these directories are present:
1. Open System Properties > Advanced > Environment Variables
2. Under "System variables", edit "Path"
3. Confirm entries such as:
- C:\Windows\System32
- C:\Windows
- C:\Program Files\Git\cmd (if using Git)
- C:\Program Files\nodejs\
You can also add an entry for the current session, or persist it with setx (note: setx truncates values longer than 1024 characters and does not affect the current session — prefer the GUI for permanent changes):
# Add to PATH for the current session only
$env:Path += ";C:\Program Files\Git\cmd"
# Persist for future sessions (user PATH)
setx PATH "$env:Path;C:\Program Files\Git\cmd"Restart your terminal after making permanent changes.
A corrupted or partial install can leave binaries missing. Do a clean reinstall:
# Remove installed packages and the lockfile
rm -rf node_modules
rm package-lock.json
# Reinstall dependencies
npm installOn Windows, if deletion fails due to locked files or long paths:
npx rimraf node_modules
npm installIf the problem persists, verify the npm cache (this checks and repairs cache integrity without deleting valid data):
npm cache verifyOnly clear the cache fully if a corrupt cache is suspected, since --force is normally discouraged by npm:
npm cache clean --forceSome packages compile native code during install and need a C/C++ toolchain plus Python. Install the appropriate tools for your platform.
Windows:
The old windows-build-tools npm package is deprecated and unmaintained — do not use it; it commonly fails on current systems. Instead, use one of these supported options:
- During Node.js installation, check "Automatically install the necessary tools... (Tools for Native Modules)" in the official installer, or
- Install the Visual Studio Build Tools directly with the "Desktop development with C++" workload from https://visualstudio.microsoft.com/downloads/, or via winget:
winget install Microsoft.VisualStudio.2022.BuildToolsModern Node.js bundles a recent Python, so a separate Python install is usually unnecessary.
macOS:
xcode-select --installLinux (Debian/Ubuntu):
sudo apt-get install build-essential python3Linux (RHEL/CentOS/Fedora):
sudo dnf groupinstall "Development Tools"If node-gyp cannot find Python, point it at the right interpreter:
npm config set python /usr/bin/python3If scripts fail on one OS but not another, use cross-platform helpers instead of shell-specific syntax.
cross-env for environment variables:
npm install --save-dev cross-env{
"scripts": {
"build": "cross-env NODE_ENV=production webpack"
}
}shx for shell-style file commands:
npm install --save-dev shx{
"scripts": {
"clean": "shx rm -rf dist"
}
}cross-spawn when you call spawn from your own Node.js code (it fixes Windows .cmd/.bat and PATHEXT resolution):
npm install cross-spawnconst spawn = require('cross-spawn');
const result = spawn.sync('npm', ['install'], { stdio: 'inherit' });Slim base images and CI runners often lack the shell or tools your scripts expect.
Docker — install what the scripts need:
# Alpine ships ash, not bash, and omits many tools
FROM node:20-alpine
RUN apk add --no-cache bash gitSpawning from Node.js code: passing shell: true lets the system shell resolve the command via PATH/PATHEXT, which often fixes ENOENT (be aware that with shell: true you must avoid passing untrusted input, since it is interpreted by the shell):
const { spawn } = require('child_process');
spawn('npm', ['install'], {
shell: true,
stdio: 'inherit'
});CI examples:
GitHub Actions — pin the shell:
- name: Install dependencies
shell: bash
run: npm installGitLab CI — install missing tools first:
before_script:
- apt-get update && apt-get install -y git### spawn vs exec
Node.js offers two main ways to run commands:
- spawn(): launches the executable directly. By default it does not run through a shell, so the binary must be resolvable directly (and on Windows, PATHEXT is not applied).
- exec(): runs the command through a shell, which handles PATH/PATHEXT resolution but is less efficient and unsafe with untrusted input.
If you maintain code that uses spawn and hits ENOENT, passing { shell: true } (or switching to cross-spawn) usually resolves it:
spawn('npm', ['run', 'build'], { shell: true });### Windows-specific resolution
1. Extensions and shims: Many Node CLIs install as .cmd/.bat shims on Windows. Plain spawn without a shell will not find them. cross-spawn handles this automatically.
2. PATHEXT: Windows uses the PATHEXT variable to know which extensions are executable; ensure it includes .COM;.EXE;.BAT;.CMD.
3. Path building: use path.join() rather than hardcoded slashes.
### WSL considerations
- npm run from a Windows terminal uses the Windows PATH; npm run from inside WSL uses the Linux PATH.
- Mixing the two (e.g. invoking /mnt/c/... Node from WSL) causes spawn errors. Pick one environment:
# From WSL, confirm you are using the Linux npm
which npm # expect /usr/bin/npm or an nvm path, not /mnt/c/...### After a Node.js upgrade
- Rebuild native modules: npm rebuild
- For nvm users, ensure the active Node's bin directory precedes system paths in PATH.
### Debugging the failing spawn call
Attach an error handler to see exactly what Node tried to launch:
const { spawn } = require('child_process');
const child = spawn('problematic-command', []);
child.on('error', (err) => {
console.error('Spawn error:', err); // err.path shows the missing executable
console.error('PATH:', process.env.PATH);
console.error('CWD:', process.cwd());
});### Packages that commonly trigger spawn/build errors
- node-sass: deprecated; needs Python and a compiler. Migrate to sass (Dart Sass), which has no native build step.
- sharp: ships prebuilt binaries for most platforms; on musl/Alpine you may need apk add --no-cache vips-dev plus build tools.
- bcrypt: needs Python and a C++ compiler. bcryptjs is a pure-JS alternative.
- sqlite3 / better-sqlite3: need build tools when no prebuilt binary matches your platform.
npm notice access token expired or revoked. Please try logging in again.
Token has expired - npm authentication failure
npm ERR! code EAI_AGAIN
How to fix "EAI_AGAIN" in npm
npm error code E403 npm error 403 Forbidden - PUT https://registry.npmjs.org/<package>
How to fix 'E403 Forbidden' error in npm
npm ERR! code EUSAGE npm ERR! Usage error
How to fix "npm ERR! code EUSAGE" in Node.js projects
npm ERR! code E401 npm ERR! 401 Unauthorized
How to fix "E401 Unauthorized" in npm