# Why Zsh Reports "node: command not found" When Using asdf-nodejs (And How to Fix It)

> Fix Zsh 'node command not found' errors when using asdf-nodejs. Learn why Zsh caches commands & how to resolve the issue simply. Get Node.js working correctly.

- Repository: [Node.js/node](https://github.com/nodejs/node)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Zsh caches command locations in an internal hash table, so if you install or switch Node.js versions after starting your shell, Zsh may still look for the binary in its old location until you run `rehash` or restart the shell.**

When managing multiple Node.js versions with **asdf-nodejs**, you might encounter a frustrating scenario: `asdf current nodejs` confirms a version is installed and active, yet Zsh responds with `zsh: command not found: node`. This issue stems from how the Zsh shell interacts with asdf's shim system rather than from the Node.js runtime itself, which resides in the `nodejs/node` repository and enters execution through `src/node.cc`.

## How asdf-nodejs Manages Node.js Versions

The asdf version manager installs each Node.js version into isolated directories under `~/.asdf/installs/nodejs/`. For example, version 20.12.0 lives at:

```

~/.asdf/installs/nodejs/20.12.0/bin/node

```

Rather than modifying your `$PATH` every time you switch versions, asdf creates a **shim**—a thin wrapper executable at `~/.asdf/shims/node`. When you type `node`, the shell should find this shim, which then reads the active version from `~/.tool-versions` and delegates to the actual binary in the installs directory.

## Why Zsh Cannot Find the node Command

### The Zsh Command Hash Table

Zsh maintains an internal **hash table** that maps command names to their absolute file system paths. When you first type `node`, Zsh searches `$PATH`, finds the shim at `~/.asdf/shims/node`, and stores this location in its hash table for faster subsequent lookups.

If you later install a new Node.js version, change the global version with `asdf global nodejs`, or open a new terminal tab where the version differs, the shim itself remains at the same path. However, if the shim was removed, regenerated, or if the shell's hash somehow points to a stale location (such as a previous manual installation that no longer exists), Zsh will report "command not found" because its cached lookup fails before it even searches `$PATH` again.

### Common Scenarios That Trigger the Error

- **Installing Node.js after starting the shell**: You opened Zsh, then ran `asdf install nodejs 20.12.0`. The shim is created, but Zsh's hash table was built before the shim existed.
- **Switching versions in an existing session**: You changed the active version with `asdf global` or `asdf local`, but Zsh still holds the old hash entry.
- **Missing initialization in `.zshrc`**: The asdf setup script that adds `~/.asdf/shims` to `$PATH` was never sourced, so Zsh has no way to discover the shim.

## Solutions to Fix "node: command not found" in Zsh

### Refresh the Command Hash with `rehash`

The fastest fix is to force Zsh to rebuild its command hash table. Run either:

```bash
rehash

```

Or the more explicit:

```bash
hash -r

```

After executing this command, Zsh will search `$PATH` anew the next time you type `node`, locating the shim at `~/.asdf/shims/node`.

### Ensure asdf Initialization is in Your Zsh Configuration

If the error persists after rehashing, verify that asdf's setup script is properly sourced in your `~/.zshrc` file. Add these lines if they are missing:

```bash
. $HOME/.asdf/asdf.sh
. $HOME/.asdf/completions/asdf.bash

```

The first line prepends `~/.asdf/shims` to your `$PATH` and sets up the `asdf` function. Without this, Zsh cannot discover the shim directory at all.

### Regenerate Shims with `asdf reshim`

In some cases, particularly after manually compiling Node.js or installing global npm packages that add binaries, the shim for `node` may be missing or corrupted. Force asdf to recreate all shims:

```bash
asdf reshim nodejs

```

This scans the `~/.asdf/installs/nodejs/` directory and recreates the wrapper scripts in `~/.asdf/shims/`.

## How the Node.js Binary is Executed

Once Zsh successfully locates the shim, the execution flow proceeds to the actual Node.js runtime. The shim at `~/.asdf/shims/node` is a small script that reads the version specified in `~/.tool-versions` and executes the corresponding binary, such as:

```

~/.asdf/installs/nodejs/20.12.0/bin/node

```

This binary is the compiled output of the `nodejs/node` repository. The interpreter's entry point is defined in **`src/node.cc`**, which initializes the V8 JavaScript engine, sets up the event loop, and begins executing your JavaScript code. When the shim delegates to this binary, the Node.js runtime launches as expected, provided the shell could find the shim in the first place.

## Summary

- **asdf-nodejs** uses shims in `~/.asdf/shims/` to delegate to version-specific binaries stored in `~/.asdf/installs/nodejs/`.
- **Zsh caches command paths** in an internal hash table; if the `node` shim appears or moves after the shell starts, Zsh may report "command not found" until the cache is cleared.
- **Fix the issue** by running `rehash` (or `hash -r`), ensuring `~/.zshrc` sources [`asdf.sh`](https://github.com/nodejs/node/blob/main/asdf.sh), or running `asdf reshim nodejs`.
- The actual Node.js runtime entry point is **`src/node.cc`** in the `nodejs/node` repository, executed once the shim successfully delegates to the version-specific binary.

## Frequently Asked Questions

### Why does `asdf current` show a Node.js version but the shell cannot find it?

`asdf current` reads the version configuration from `.tool-versions` files and the asdf installation directory independently of the shell's command resolution. If Zsh's internal command hash table contains a stale entry or if the asdf shim directory is not in your `$PATH`, the shell will fail to locate the `node` executable even though asdf knows which version should be active.

### What is the difference between `rehash` and `hash -r` in Zsh?

Both commands force Zsh to rebuild its internal command hash table, causing the shell to search `$PATH` again for command locations the next time you execute them. `rehash` is the Zsh-specific built-in command, while `hash -r` is the POSIX-compatible syntax that also works in Bash and other shells. In Zsh, they are functionally equivalent for clearing the command cache.

### When should I use `asdf reshim nodejs` instead of just rehashing?

Run `asdf reshim nodejs` when the shim executable itself is missing from `~/.asdf/shims/` or when you have installed global npm packages that provide new binaries. Rehashing only updates Zsh's cache of where commands are located; it cannot help if the shim file does not exist. Reshiming regenerates all wrapper scripts in the shims directory based on the current contents of the `~/.asdf/installs/nodejs/` directory.

### Does this issue affect Bash or other shells besides Zsh?

While this article focuses on Zsh, Bash can exhibit similar behavior through its own command hashing mechanism (`hash -r` also works in Bash). However, Zsh is more aggressive about caching command locations and is the default shell on macOS since Catalina, making this issue particularly common for Zsh users. Fish shell handles PATH changes differently and typically does not require manual rehashing.