How to fix Error: /bin/sh: command: command not found (exec failed) in Node.js

Node.jsINTERMEDIATEMEDIUMUpdated Dec 9, 2025· 160 views

This error occurs when Node.js child_process.exec() tries to execute a command that cannot be found by the shell (/bin/sh). The shell either cannot locate the executable in PATH or the command does not exist on the system.

Quick fix

Fixes ENOENT

which <command-name>
# or
command -v <command-name>
  1. Verify the command exists on your system
  2. Check and pass the PATH environment variable
  3. Use absolute paths for executables
  4. Specify a different shell
node.js — error
which <command-name>
# or
command -v <command-name>
Error: /bin/sh: command: command not found (exec failed)

What this error means

This error appears when using Node.js's `child_process.exec()` or related functions to execute a shell command. The `exec()` function spawns a shell (by default `/bin/sh` on Unix systems) to run your command. When you see "command not found," it means the shell could not locate the executable you're trying to run. The `/bin/sh` prefix indicates that Node.js successfully spawned the shell, but the shell itself failed to find the command. This is different from an ENOENT error on the shell path itself, which would prevent the shell from starting at all. This commonly happens when the command is not installed, not in the system PATH, or when the environment variables available to the child process differ from your normal shell environment. Docker containers and CI/CD environments are particularly prone to this issue because they often have minimal installations and different PATH configurations.

Typical symptoms

  • Error message shows "/bin/sh: <command>: command not found"
  • Command works in your terminal but fails in Node.js exec()
  • Different behavior between development and Docker containers
  • Commands installed with npm/yarn globally fail in child processes
  • Scripts work on host machine but fail in CI/CD pipelines

Common causes

  1. The command is not installed in the system or container
  2. The executable is not in the PATH environment variable
  3. PATH environment differs between parent process and child process
  4. Command is installed for a different user than the one running the process
  5. Using a Docker container with a minimal base image (alpine) missing common utilities
  6. Node.js executable installed via NVM but PATH not configured correctly
  7. Custom env option passed to exec() without including PATH
  8. Command requires bash features but /bin/sh points to a simpler shell

How to fix "Error: /bin/sh: command: command not found (exec failed)"

1Verify the command exists on your system

First, check if the command is actually installed. Run this in your terminal:

bash
which <command-name>
# or
command -v <command-name>

If this returns nothing, the command is not installed or not in PATH. Install it using your package manager:

bash
# Ubuntu/Debian
sudo apt-get update && sudo apt-get install <package-name>

# Alpine (Docker)
apk add <package-name>

# macOS
brew install <package-name>
2Check and pass the PATH environment variable

When you pass a custom env object to exec(), it completely replaces the environment, including PATH. Always include PATH:

javascript
const { exec } = require('child_process');

// ❌ Wrong - this removes PATH
exec('mycommand', {
  env: { MY_VAR: 'value' }
}, (error, stdout, stderr) => {
  // Will fail with "command not found"
});

// ✅ Correct - preserve PATH
exec('mycommand', {
  env: {
    ...process.env,  // Include existing environment
    MY_VAR: 'value'
  }
}, (error, stdout, stderr) => {
  if (error) {
    console.error(`Error: ${error.message}`);
    return;
  }
  console.log(stdout);
});
3Use absolute paths for executables

Instead of relying on PATH, use the absolute path to the executable:

javascript
const { exec } = require('child_process');

// Find the absolute path first
const { execSync } = require('child_process');
try {
  const commandPath = execSync('which node', { encoding: 'utf-8' }).trim();
  console.log('Node path:', commandPath);

  // Use absolute path
  exec(`${commandPath} --version`, (error, stdout, stderr) => {
    if (error) {
      console.error(`Error: ${error.message}`);
      return;
    }
    console.log(stdout);
  });
} catch (error) {
  console.error('Command not found');
}

For npm/yarn global packages:

javascript
const { exec } = require('child_process');
const path = require('path');

// npm global bin directory
const npmBin = execSync('npm bin -g', { encoding: 'utf-8' }).trim();
const commandPath = path.join(npmBin, 'mycommand');

exec(commandPath, (error, stdout, stderr) => {
  // ...
});
4Specify a different shell

If your command requires bash features (aliases, functions), explicitly use bash instead of /bin/sh:

javascript
const { exec } = require('child_process');

exec('mycommand', {
  shell: '/bin/bash'  // Use bash instead of sh
}, (error, stdout, stderr) => {
  if (error) {
    console.error(`Error: ${error.message}`);
    return;
  }
  console.log(stdout);
});

Note: This only helps if the command exists but requires bash-specific features. It won't help if the command isn't in PATH.

5Fix Docker container PATH issues

In Dockerfiles, ensure commands are installed and PATH is configured:

dockerfile
FROM node:18-alpine

# Install required commands
RUN apk add --no-cache git bash curl

# If using npm global packages, add to PATH
ENV PATH="/usr/local/bin:$PATH"

# For NVM installations
ENV NVM_DIR="/root/.nvm"
RUN source "$NVM_DIR/nvm.sh" && nvm install node

# Create symlinks if using a non-root user
RUN ln -s /usr/local/bin/node /usr/bin/node
RUN ln -s /usr/local/bin/npm /usr/bin/npm

COPY . /app
WORKDIR /app

CMD ["node", "index.js"]

When using docker-compose exec:

bash
# Pass environment variables explicitly
docker-compose exec -e PATH=$PATH app node script.js

# Or ensure PATH is set in docker-compose.yml
# services:
#   app:
#     environment:
#       - PATH=/usr/local/bin:/usr/bin:/bin

Advanced notes

Understanding exec() vs spawn(): The exec() function spawns a shell and runs commands through it, while spawn() runs executables directly. If you're executing a known binary without shell features, spawn() is more efficient and avoids shell lookup issues:

javascript
const { spawn } = require('child_process');
const child = spawn('/usr/bin/node', ['--version']);

PATH lookup order: When a shell looks for a command, it searches directories in PATH from left to right. You can see your PATH with console.log(process.env.PATH). If multiple versions of a command exist, the first match is used.

Alpine Linux considerations: Alpine uses musl libc instead of glibc and has a minimal set of installed utilities. Many commands you expect on Ubuntu/Debian won't exist on Alpine by default. Always install required dependencies explicitly in Alpine-based containers.

NVM and PATH persistence: If you install Node.js via NVM in a Dockerfile, the PATH modifications are not automatically available to child processes. You must either source the NVM script in each shell command or use absolute paths to the NVM-installed binaries (typically in ~/.nvm/versions/node/*/bin/).

Security implications: Using absolute paths is more secure than relying on PATH, as it prevents PATH injection attacks where a malicious actor places a fake executable earlier in PATH to intercept your commands.

Error handling best practices: Always handle the 'error' event in child processes. Check error.code for ENOENT specifically, and provide helpful messages directing users to install missing dependencies.

Frequently asked questions

What does "ENOENT" mean?
exec() or related functions to execute a shell command. The exec() function spawns a shell (by default /bin/sh on Unix systems) to run your command. When you see "command not found," it means the shell could not locate the executable you're trying to run.
How do I fix "ENOENT"?
This error occurs when Node.js child_process.exec() tries to execute a command that cannot be found by the shell (/bin/sh). The shell either cannot locate the executable in PATH or the command does not exist on the system.
What causes "ENOENT"?
The command is not installed in the system or container The executable is not in the PATH environment variable PATH environment differs between parent process and child process
Is the "ENOENT" error serious?
It is a medium-severity error — more of a blocker than a risk. The steps above resolve it.

Official resources & further reading