Migrate to RunxBuild and earn up to $50 in hosting credit on your first deposit.

Calculate your savings
unxBuild
Back to Blog Troubleshooting

npm Not Found: Every Reason It Happens and the Fix for Each One

Sean

Platform Writer

Jun 20, 2026
7 min read

“npm not found” is not one error, it is at least four. The shell is telling you the binary it tried to invoke did not resolve, and which binary it was looking for, and in what state your install is, are all things you have to figure out from a single line. The fix is different for each cause, so the wrong fix is the most common outcome of trying one.

The four causes, in order of how often they bite a fresh install: Node was never installed at all, Node is installed but the npm shim is missing, npm is on disk but the shell’s PATH does not include the directory it lives in, or the shell session is stale and is still looking at a PATH from before you installed Node. There is a fifth cause that shows up in CI and Docker builds — Node is installed in one layer but the PATH change happens in a layer the running step does not inherit.

The diagnostic is six commands long, takes ten seconds to run, and tells you which of those four causes is the one. The fix is then mechanical. No more guessing at bash_profile exports, no more reinstalling Node and hoping the second time takes.

npm not found: every reason it happens and the fix for each one

Table of contents

The four causes of “npm not found”

The error message command not found: npm is the shell telling you the lookup for npm on PATH returned nothing. There are only four things that can be true at that point.

Node was never installed. You ran the macOS installer, the Linux package manager, or unzipped a tarball, but the install either failed silently, landed in a directory the shell does not search, or never happened. Check with which node — if that also returns nothing, you are in this bucket.

Node is installed but npm is missing. This is the partial-install case. A truncated download, an interrupted package install, a Node version manager that installed the runtime but skipped the package manager, or a manual chmod that wiped the npm directory. which node works, which npm does not.

Node and npm are both installed but the shell cannot find npm. This is the PATH problem. The directory npm lives in (usually the same as Node, sometimes one level up) is not in the shell’s PATH. The binary is on disk; the shell just does not know to look there.

The shell session is stale. You installed Node in a new terminal, then tried to run npm in the terminal you had open before the install. The PATH for the new install is set in ~/.zshrc or ~/.bashrc, and the old session loaded its config before that change existed. Open a new terminal, and the error disappears.

The fifth cause, less common but worth knowing: the binary exists but is not executable. A chmod -x somewhere, or a filesystem mounted with noexec. ls -la $(which npm) tells you, when you find it.

The ten-second diagnostic

Run these six commands in order. Each one takes a second and tells you which of the four causes is yours.

which node
which npm
node --version
npm --version
npm config get prefix
echo "$PATH"

If which node returns nothing: Node is not installed. Go install it. Skip the rest of the diagnostic.

If which node returns a path and which npm does not: the partial-install case. Reinstall Node through the same channel that put the runtime there (nvm, the system package manager, the official installer) and let it finish.

If both which return paths and which npm returns a path that is not in echo "$PATH": the PATH problem. The directory npm lives in has to be added to PATH for the running shell, or the path you see has to be added permanently to your shell config.

If both which return paths that are in PATH but the binaries still fail to run: permissions, filesystem mount, or a corrupted install. ls -la on the binary and reinstall if the install is corrupt.

If both which work and you are in a shell that has been open since before you installed Node: the stale session. Close the terminal, open a new one, run npm --version again.

The order matters. which first, because the cheapest answer is “the binary does not exist.” Then node --version and npm --version, because either one of those failing tells you a different story. Then npm config get prefix to find the directory the binary should be in. Then echo "$PATH" last, because comparing the two is what tells you whether the directory is reachable.

The fix for each cause

Node was never installed. Use nvm (Node Version Manager). The install is one curl, and you do not need sudo. The reason nvm is the right answer is covered in the next section, but even for a one-off, nvm is faster and more reliable than the official installer because it does not touch /usr/local and does not need a PATH export to work.

Node is installed but npm is missing. Reinstall through the same channel. If you used nvm, nvm install <version> again — it is idempotent and will rebuild the missing pieces. If you used the official installer, run the installer again; it detects the existing install and re-puts npm in place.

The PATH problem. Add the directory npm lives in to PATH in your shell config. For zsh:

echo 'export PATH="$(npm config get prefix)/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc

For bash, the same with ~/.bashrc. The $(npm config get prefix) is the right way to do it because the prefix changes with the install method. Hardcoding /usr/local/bin or ~/.npm-global/bin works until the next time you switch install methods.

The stale session. Open a new terminal. That is the fix. If you have a workflow that depends on a long-running shell, restart it after the install.

Why nvm is the right answer

nvm installs Node into a per-user directory (~/.nvm/versions/node/<version>/), does not require sudo, does not touch the system package manager, and makes it trivial to run multiple Node versions side by side. The npm binary lives next to the node binary inside that directory, so which npm after an nvm install always returns a path inside the nvm tree, and nvm automatically prepends the right directory to PATH when you switch versions.

Three concrete reasons to prefer nvm over the official installer or the system package manager:

No sudo. The system package manager route (apt install nodejs npm) installs Node into /usr and requires root. It also tends to lag behind current Node releases. nvm is per-user and is the same version the rest of the team is using.

No PATH fights. nvm hooks into the shell and prepends the right directory on demand. The shell config it adds is three lines. The shell config the official installer adds is fifteen lines and tends to collide with other tools’ PATH edits.

Per-project Node version. A repo with a .nvmrc file is the canonical way to pin the Node version. nvm use reads the file and switches the runtime. No more node 20 is on the dev box, 18 is in CI, the docs say 16 mess.

The trade-off: nvm is a shell function, not a binary, so it does not survive a non-interactive shell the way a binary on PATH would. That is the one corner where you reach for the official installer or the Docker base image with Node pre-installed. For interactive development, nvm is the answer.

The CI/CD version of the same error

In CI, the same npm: command not found shows up for a different reason. The runner image has Node installed in one step, but the next step runs in a fresh shell that does not inherit the PATH change. The GitHub Actions example:

steps:
  - uses: actions/setup-node@v4
    with:
      node-version: 20
  - run: npm install
  - run: npm test

actions/setup-node adds Node to PATH for every step. A manual install via apt-get install nodejs does not — each step gets a fresh shell, and the PATH change is lost between steps. The fix is to either use the official setup action, or to run all the npm commands in one step.

GitLab CI has the same shape. The default node image includes npm. A custom image with Node but without npm on PATH is the common cause of the error in CI logs.

The diagnostic in CI: add a step that runs which node && which npm && node --version && npm --version immediately before the failing command. The output will tell you which of the four causes is the one.

The Docker version of the same error

In Docker, the same error usually means the RUN npm install step ran in a layer where the install completed, but the runtime Node binary the rest of the image uses is in a different location. Multi-stage builds are the most common cause — the builder stage has npm, the runtime stage pulls the artifacts from the builder but does not have npm, and an ENTRYPOINT or CMD that tries to run npm at runtime fails.

# Wrong
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM node:20-slim
WORKDIR /app
COPY --from=builder /app ./
CMD ["npm", "start"]

The slim image has npm on PATH, so this works. But a FROM gcr.io/distroless/nodejs20-debian12 runtime does not. The fix is to invoke the binary directly, not through npm:

# Right for distroless
CMD ["node", "server.js"]

The rule: if the runtime image has npm, you can use it. If it does not, the entry point has to invoke node directly. The npm script is a developer convenience, not a runtime artifact.

A managed platform that runs your service with the right Node version and gives you build logs and deploy logs in the same place takes the install story out of your Dockerfile entirely. You write the package.json, the platform runs npm install during build, the runtime image is whatever the platform chooses, and the entry point is the start command you set in the dashboard. The “npm not found” error is one the platform has to fix, not you.

How this fits the rest of the stack

An environment where npm install works the same on every developer machine, in CI, and in production is worth more than any individual package manager. The RunxBuild hosting calculator is the right place to model what that environment costs — pick the runtime size, the build frequency, the bandwidth the build artifacts consume, and the secrets the build pipeline reads, and the calculator shows what the platform actually costs at the team’s actual usage rather than what the free tier hides.

Useful related references:

FAQ

What does “npm not found” actually mean?

It means the shell looked for the npm binary in every directory listed in PATH and did not find it. The binary may not exist, may be in a directory not on PATH, or may exist with the wrong permissions. The error is the same in every case, which is why the diagnostic matters.

Why does it say “command not found” instead of something more helpful?

Because the shell itself is what is reporting the error, not npm. The shell’s command not found is the same message for every binary it cannot resolve. Bash, zsh, fish — all the same wording, all the same root cause. Run the diagnostic in the article to figure out which of the four causes is yours.

Do I need to reinstall Node to fix this?

Sometimes, but not always. If npm is missing because of a partial install, reinstalling Node through the same channel fixes it. If the problem is PATH or a stale session, you do not need to reinstall anything. Run the diagnostic first to know which case you are in.

How do I add npm to my PATH permanently?

Add export PATH="$(npm config get prefix)/bin:$PATH" to your ~/.zshrc (or ~/.bashrc for bash) and source the file. The npm config get prefix lookup makes the export portable across install methods.

What is the difference between nvm, nvs, and the official Node installer?

nvm and nvs are both version managers — they let you install multiple Node versions side by side and switch between them per shell. The official installer installs one Node version system-wide. nvm is per-user, nvs is similar, and the official installer requires sudo. For development, nvm or nvs is the right call.

Why does npm work in a new terminal but not the one I have open?

Because the PATH change happened in a shell config file (~/.zshrc, ~/.bashrc), and the open terminal already loaded that file before the change existed. Open a new terminal, or source the file in the current one, to pick up the new path.

Does this error look the same in Windows?

The error wording is slightly different ('npm' is not recognized as an internal or external command in cmd, or npm: The term 'npm' is not recognized in PowerShell), but the causes are the same four. The Windows-specific wrinkle is that the Node MSI installer has to add the install directory to the system PATH for npm to resolve, and on managed Windows installs that step can be blocked by policy.

#npm#Node.js#PATH#Installation#Command Line