Skip to content
Latchkey

concurrently "command not found" / Non-Zero Exit - Fix Parallel Scripts in CI

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

  1. Use --kill-others-on-fail deliberately so one failure tears down the rest.
  2. Set --success semantics if only some commands must succeed (e.g. long-running dev servers in tests).
  3. 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: Build
  shell: bash
  run: |
    set -euo pipefail
    npm 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.

Related guides

References

Not every red build is your code. Latchkey repairs the ones that are not, on the runner. Start free → 30-day trial · No credit card