concurrently "command not found" / Non-Zero Exit - Fix Parallel Scripts in CI
By Daniel Zoghalchali·Latchkey
concurrently runs several npm commands in parallel. It fails in CI when the binary itself is missing (a stripped devDependency), or when one of the parallel commands exits non-zero and concurrently reports the whole run as failed.
What this error means
A concurrently step fails with concurrently: not found, or it runs but exits non-zero because one of the parallel tasks failed. The first case is an install problem; the second is one child command’s real error.
npm output
sh: 1: concurrently: not found
npm error code 127
# or
[1] npm run server exited with code 1
--> Sending SIGTERM to other processes..
concurrently exited with code 1
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
concurrently not installed for this job
concurrently is a devDependency; a --omit=dev install strips it, so the binary is missing (exit 127).
One parallel command failed
By default concurrently fails the run if any command exits non-zero. The real error is in that child command’s output, not concurrently itself.
How to fix it
Install it and read the failing child
Ensure concurrently is present, and find which parallel command actually failed.
Terminal
npm install -D concurrently
# quote each command; name them to read logs:
npx concurrently -n api,web "npm:dev:api" "npm:dev:web"
Tune kill/success behavior
Use --kill-others-on-fail deliberately so one failure tears down the rest.
Set --success semantics if only some commands must succeed (e.g. long-running dev servers in tests).
Quote each command so shell parsing does not split it.
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
Keep concurrently in devDependencies and installed for the job.
Name parallel commands so failures are easy to trace.
Configure kill/success behavior to match intent.
Frequently asked questions
What causes concurrently "command not found" / Non-Zero exit?
There are 2 common causes: concurrently not installed for this job and one parallel command failed. concurrently is a devDependency; a --omit=dev install strips it, so the binary is missing (exit 127).
How do I fix concurrently "command not found" / Non-Zero exit?
There are 2 fixes depending on which cause you have: install it and read the failing child and tune kill/success behavior. Work through them in order, since the first is the most common.
What does concurrently "command not found" / Non-Zero exit actually mean?
A concurrently step fails with concurrently: not found, or it runs but exits non-zero because one of the parallel tasks failed.
How do I stop concurrently "command not found" / Non-Zero exit happening again?
Keep concurrently in devDependencies and installed for the job. The prevention section lists 3 changes that keep it from recurring.