Node "spawn ENOENT" for a Child Process in CI - Fix the Missing Executable
By Kaveh Alemi·Latchkey
spawn ENOENT means child_process could not find the executable you asked it to run. The binary is not on PATH on the CI runner.
What this error means
A node process that shells out throws Error: spawn <command> ENOENT. The command runs locally but the executable is absent from the runner.
node
Error: spawn git ENOENT
at ChildProcess._handle.onexit (node:internal/child_process:286:19)
at onErrorNT (node:internal/child_process:484:16) {
errno: -2, code: 'ENOENT', syscall: 'spawn git'
}
Diagnose it: the shell in CI is not your shell
Package scripts run under a different shell, a different PATH, and a non-interactive environment on a runner. Most scripts that fail only in CI are relying on something the login shell gave them locally: a tool on PATH, an environment variable from a dotfile, or a TTY.
Terminal
# what the script can actually see
npm run env | grep -E "^(PATH|NODE_ENV|CI)="
# is the binary on PATH for the script, not just for you?
npm exec -- which <tool> || echo "not resolvable from npm scripts"
# run the exact script with tracing
sh -x -c "$(node -p "require('./package.json').scripts.build")"
Common causes
The executable is not installed on the runner
The CI image lacks the binary the child process invokes, so spawn cannot locate it.
A typo or a shell builtin spawned without a shell
A misspelled command, or a shell builtin spawned without shell: true, has no matching executable on PATH.
How to fix it
Install the executable in CI
Add a setup step that installs the required binary.
For a shell builtin or pipeline, pass shell: true to spawn.
Otherwise verify the command name is spelled correctly.
JavaScript
spawn('dot -V', { shell: true });
Make failures fail the job
A multi-command script can report success while a middle command failed, which produces the worst kind of CI result: a green build that shipped something broken.
.github/workflows/ci.yml
# pipefail is NOT set by default in every runner shell- name:Buildshell:bashrun:|set -euo pipefailnpm run build | tee build.log
How to prevent it
Install every external binary your scripts spawn as an explicit CI setup step, verify command names, and prefer absolute paths or shell: true where appropriate.
Frequently asked questions
What causes Node "spawn ENOENT" for a child process in CI?
There are 2 common causes: the executable is not installed on the runner and a typo or a shell builtin spawned without a shell. The CI image lacks the binary the child process invokes, so spawn cannot locate it.
How do I fix Node "spawn ENOENT" for a child process in CI?
There are 2 fixes depending on which cause you have: install the executable in ci and run shell builtins through a shell. Work through them in order, since the first is the most common.
What does Node "spawn ENOENT" for a child process in CI actually mean?
A node process that shells out throws Error: spawn <command> ENOENT.
How do I stop Node "spawn ENOENT" for a child process in CI happening again?
Install every external binary your scripts spawn as an explicit CI setup step, verify command names, and prefer absolute paths or shell: true where appropriate.