Skip to content

Fix: npm ERR! cb() never called

FixDevs · (Updated: )

Part of:  JavaScript & TypeScript Errors

Quick Answer

Resolve npm's cb() never called error by clearing cache, fixing network issues, updating npm, and resolving corrupted package-lock.json files.

The Error

When running npm install (or any npm command), you hit this cryptic error:

npm ERR! cb() never called!
npm ERR! not ok code 0

npm ERR! This is an error with npm itself. Please report this error at:
npm ERR!     <https://npm.community>

Or, in newer npm versions, you might see a slightly different format:

npm ERR! cb() never called!

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/user/.npm/_logs/2026-06-06T12_00_00_000Z-debug-0.log

Unlike most npm errors that point to a specific package or configuration problem, this one gives you almost nothing to work with. The cb() refers to an internal callback function inside npm that was expected to execute but never did. Something interrupted npm’s process before it could finish.

Why This Happens

The “cb() never called” error is npm’s generic way of saying “something went wrong internally, and I don’t know what.” It is not a single bug — it is a symptom that can be triggered by multiple underlying causes.

The most common triggers are:

  1. Corrupted npm cache. npm stores downloaded packages in a local cache (~/.npm on Linux/macOS, %AppData%\npm-cache on Windows). If files in this cache are incomplete or corrupted — from a previous interrupted install, a disk issue, or even an npm bug — npm may fail silently and never invoke its completion callback.

  2. Network interruptions. A flaky connection, corporate proxy, VPN timeout, or DNS resolution failure can cause npm to hang while downloading a package. When the connection drops mid-download, npm sometimes fails to handle the error gracefully and surfaces this callback error instead.

  3. Corrupted package-lock.json. The lockfile can get into an inconsistent state after merge conflicts, manual edits, or interrupted installs. When npm tries to resolve dependencies from a malformed lockfile, it can enter an unrecoverable state.

  4. Outdated npm version. Older npm versions (especially npm 5.x and early 6.x) had bugs that directly caused this error. Many of these were fixed in later releases.

  5. File system permission issues. npm needs write access to node_modules, the cache directory, and temporary directories. Permission problems can cause silent failures.

  6. Disk space exhaustion. If the disk fills up during installation, write operations fail and npm cannot complete its internal callbacks.

  7. Node.js and npm version incompatibility. Running a version of npm that was not designed for your current Node.js runtime can cause unexpected internal failures.

Let’s fix it, starting with the most likely solutions.

Platform and Environment Differences

The “cb() never called” error is disproportionately driven by environment — the same package.json reliably installs in one place and reliably fails in another. Knowing where you are on the platform/version matrix narrows the diagnosis fast.

Node.js versions matter more than people think. Node 12 was the last major release where the legacy callback-based npm internals were heavily exercised in everyday installs — the “cb()” error was at its peak. Node 16 (npm 7+) rewrote large parts of the install path to use Promises end-to-end; the error is much rarer. Node 18 LTS, Node 20 LTS, and Node 22 LTS continue this trend. If you are still hitting this on Node 18+, the cause is almost certainly an external one (network, disk, antivirus) rather than an npm bug.

npm 6 vs npm 7+ install behavior. npm 6 used the legacy arborist predecessor and installed peer dependencies implicitly. npm 7 introduced automatic peer dependency installation, which dramatically changed the dependency graph and surfaced cb() errors when peer chains conflicted with the resolver’s expectations. npm 9 and 10 are stricter still and will hard-fail on cases where npm 6 would silently install something inconsistent. If you cannot move forward, downgrading to a recent npm temporarily (npm install -g npm@10) sometimes unblocks an install that npm 11 prerelease refuses.

Yarn 1 (Classic) vs Yarn Berry vs pnpm. Yarn 1 still works around many of the cases that trigger this error in npm. Yarn Berry (2+) uses Plug’n’Play by default and has its own failure modes (ZipOpenError, MODULE_NOT_FOUND) but rarely the cb() pattern. pnpm uses a content-addressable store and symlinks node_modules — Windows users without Developer Mode enabled cannot create symlinks and see cryptic failures that look like cb() but are actually permission errors.

macOS Intel vs Apple Silicon. Some native dependencies (sharp, node-canvas, bcrypt, node-sass, better-sqlite3) ship pre-built arm64 binaries only in recent versions. On older project lockfiles, npm tries to download an x86_64 binary, fails, falls back to build-from-source, and the build step hangs without ever calling its callback. On macOS, also watch for the Gatekeeper quarantine attribute on freshly downloaded npm binaries:

xattr -dr com.apple.quarantine ~/.npm

Linux fs.inotify limits. On Linux, large node_modules trees can exceed fs.inotify.max_user_watches (default 8192 on older distros, 65536+ on newer ones). When inotify watches are exhausted, file watchers in postinstall scripts hang silently. Symptoms include npm appearing to stall right before completion. Raise the limit:

echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p

Windows native (PowerShell vs cmd vs WSL2). Windows has the most variants of this error. Long paths inside node_modules exceed the 260-character MAX_PATH limit and cause silent failures during file extraction. Symlink-based package managers (pnpm, npm’s --link mode) require Developer Mode or administrator privileges. Antivirus software (Defender, Norton, McAfee) scans every file npm extracts, often locking files mid-write and causing the callback chain to never resolve. Exclude %AppData%\npm-cache and your project directory from real-time scanning while installing. PowerShell’s npm install and cmd’s npm install should behave identically — if they don’t, you have two npm installs on PATH (typically one in C:\Program Files\nodejs\ and one in %AppData%\npm\). Use Get-Command npm -All to spot the conflict.

WSL2 specifically. Running npm install on a project under /mnt/c/... cross-mounts the NTFS filesystem and is 5–10x slower for node_modules operations. Worse, the cb() error appears far more often there because file locks behave differently across the boundary. Move the project into the Linux filesystem (~/projects/...) before running npm.

Docker containers. Bind-mounting node_modules from the host into a Linux container with -v ./:/app re-uses host-compiled native modules. When the host is macOS or Windows and the container is Linux, every native module is the wrong binary and fails on require. Use a named volume for node_modules or install inside the container in your Dockerfile. Multi-stage builds that copy node_modules between architectures (e.g., building on linux/amd64 and deploying to linux/arm64) have the same problem.

GitHub Actions / GitLab CI. npm ci is the right command on CI — it is deterministic and skips peer resolution. actions/cache for ~/.npm reduces install time but introduces its own cb() risk when the cache key collides across Node versions in a matrix. Always include the Node version and the OS in the cache key:

key: ${{ runner.os }}-node-${{ matrix.node }}-${{ hashFiles('**/package-lock.json') }}

GitHub Actions runners have ephemeral disks with generous space, but ubuntu-latest upgraded to use 80GB SSDs in 2024 — older Ubuntu 20.04 runners had only 14GB and frequently hit the disk-space cause.

Fix 1: Clear the npm Cache

This resolves the error in the majority of cases. A corrupted cache is the single most common cause of “cb() never called.”

npm cache clean --force

The --force flag is required since npm 5. Without it, npm refuses to clean the cache because it is supposed to be self-healing. In practice, the self-healing mechanism does not always work.

After clearing the cache, retry your install:

npm install

If you want to verify the cache integrity before clearing it (to confirm corruption is the issue):

npm cache verify

This will report any corrupted entries and attempt to fix them. If it reports issues, follow up with the full npm cache clean --force.

Fix 2: Delete node_modules and package-lock.json

If clearing the cache alone didn’t work, the problem may be in your project’s existing dependency tree. Remove everything and start fresh:

rm -rf node_modules package-lock.json
npm cache clean --force
npm install

On Windows (Command Prompt):

rmdir /s /q node_modules
del package-lock.json
npm cache clean --force
npm install

This three-step approach eliminates corrupted cached packages, stale lockfile entries, and partially installed modules all at once. It is the most thorough local fix.

Common Mistake: Deleting node_modules but leaving package-lock.json in place. If the lockfile itself is corrupted or contains stale resolution data, npm will try to follow the same broken resolution path again. Always remove both when troubleshooting this error.

Fix 3: Update npm

Many “cb() never called” occurrences were caused by bugs in npm itself that were fixed in later versions. Update npm to the latest release:

npm install -g npm@latest

Check your current version before and after:

npm --version

If you are on npm 5.x or early 6.x, upgrading is especially important. These versions had known issues with callback handling during network failures and cache operations.

If the global install itself fails with the same error, you can update npm through Node.js instead:

# Install nvm (Node Version Manager) if you don't have it
# Then install the latest LTS Node.js, which includes a recent npm
nvm install --lts
nvm use --lts

If you get permission errors during global npm installs, see Fix: EACCES permission denied when installing npm packages globally for the proper fix — don’t use sudo.

Fix 4: Fix Network and Proxy Issues

Network problems are the second most common cause. npm might hang on a download, time out, and then fail with the callback error.

Test your connection to the npm registry:

npm ping

If this times out or fails, you have a network issue.

If you are behind a corporate proxy:

npm config set proxy http://your-proxy-server:port
npm config set https-proxy http://your-proxy-server:port

If a proxy was set but you don’t need one (common after switching from a corporate to a personal network):

npm config delete proxy
npm config delete https-proxy

If you suspect SSL issues (common behind corporate firewalls that perform SSL inspection):

npm config set strict-ssl false

Only use this as a diagnostic step. If it fixes the issue, talk to your network team about adding the npm registry’s certificate to your trusted certificates rather than disabling SSL verification permanently.

Increase the network timeout if you are on a slow connection:

npm config set fetch-retry-mintimeout 20000
npm config set fetch-retry-maxtimeout 120000
npm config set fetch-retries 5

These settings give npm more time and more attempts to complete downloads before giving up.

Fix 5: Switch the npm Registry

The default npm registry (https://registry.npmjs.org/) may be experiencing issues, or your network may be blocking it. Try switching to a mirror:

# Check current registry
npm config get registry

# Switch to a mirror (example: npmmirror for users in China)
npm config set registry https://registry.npmmirror.com/

# Or use the Yarn registry as an alternative
npm config set registry https://registry.yarnpkg.com/

After testing, if the mirror works, the problem is either with the default registry or with your network’s connection to it. You can switch back after the issue resolves:

npm config set registry https://registry.npmjs.org/

If you are using a private registry (Artifactory, Verdaccio, GitHub Packages) and getting this error, verify that the registry is accessible and your authentication tokens are valid:

npm whoami --registry https://your-private-registry.com/

Fix 6: Check Disk Space

npm needs space for downloading packages, extracting them, and writing to node_modules. If your disk is full, npm will fail in unexpected ways — including the callback error.

# Linux/macOS
df -h

# Windows (PowerShell)
Get-PSDrive C

A typical node_modules folder can be hundreds of megabytes to several gigabytes. Make sure you have at least 1-2 GB of free space.

If space is tight, clean up old npm caches and unused node_modules directories:

# Clear npm cache
npm cache clean --force

# Find large node_modules directories (Linux/macOS)
du -sh ~/projects/*/node_modules 2>/dev/null | sort -hr | head -20

This situation is also common in Docker containers with limited disk space. If you are hitting this in a Docker build, see the CI/CD section below. Inside containers, the /tmp directory often has a tiny default size — df -h /tmp shows whether npm’s extraction is exhausting it.

Fix 7: Fix Node.js Version Compatibility

Certain npm versions do not work correctly with certain Node.js versions. This mismatch can cause internal errors including the callback issue.

Check your current versions:

node --version
npm --version

The general rule: use the npm version that ships with your Node.js version. You can check which npm version comes with which Node.js release at the Node.js releases page.

If you have manually upgraded or downgraded npm independently of Node.js, you may have introduced a compatibility issue. Reset to the bundled version:

# If using nvm
nvm install-latest-npm

# If not using nvm, reinstall Node.js from nodejs.org
# This will restore the matching npm version

Pro Tip: Use a .nvmrc or .node-version file in your project root to pin the Node.js version across your team. This prevents “works on my machine” issues caused by version mismatches. Create it with node --version > .nvmrc and team members can simply run nvm use to switch to the correct version.

Using a version manager like nvm (Linux/macOS) or nvm-windows also prevents the EACCES permission errors that come from installing Node.js system-wide — node binaries owned by root force you into sudo npm, which then writes cache files only root can later read.

Fix 8: Handle package-lock.json Corruption

The lockfile can become corrupted in several ways: merge conflicts that were resolved incorrectly, manual edits that broke the JSON structure, or interrupted npm install runs that left the file in a partial state.

Signs of lockfile corruption:

  • The file has merge conflict markers (<<<<<<<, =======, >>>>>>>)
  • The JSON is malformed (missing brackets, trailing commas)
  • Integrity hashes are mismatched or missing

Regenerate the lockfile:

rm package-lock.json
npm install

If your project uses npm ci in production or CI (which requires a lockfile), make sure to commit the newly generated package-lock.json.

If you hit merge conflicts in package-lock.json during a git merge or rebase, the safest resolution is almost always to delete the lockfile and regenerate it rather than trying to resolve the conflicts manually. The lockfile is auto-generated — treat it that way:

# After a merge conflict in package-lock.json
git checkout --theirs package-lock.json
rm package-lock.json
npm install
git add package-lock.json

This accepts the incoming version, immediately discards it, and regenerates the file based on the merged package.json. Treat the lockfile like a build artifact — never resolve conflicts inside it by hand.

Fix 9: Fix Permissions

On Linux and macOS, permission issues with npm’s cache directory or global install directory can cause silent failures.

Check ownership of the npm cache:

ls -la ~/.npm

If the directory is owned by root (which happens if you’ve ever run npm install with sudo), fix the ownership:

sudo chown -R $(whoami) ~/.npm

Check the temporary directory. npm uses the system temp directory during installs. If it is not writable:

# Check the temp directory npm is using
npm config get tmp

# Make sure it is writable
ls -la $(npm config get tmp)

On Windows, permission issues are less common but can occur if you are running your terminal without the required access level or if antivirus software is blocking npm from writing to node_modules.

Fix 10: Fix Issues in CI/CD Environments

The “cb() never called” error is disproportionately common in CI/CD pipelines (GitHub Actions, GitLab CI, Jenkins, CircleCI) due to resource constraints and network conditions.

Use npm ci instead of npm install:

npm ci

npm ci is designed for automated environments. It deletes node_modules before installing, installs exact versions from the lockfile (no resolution needed), and is faster and more deterministic. It is less likely to trigger the callback error because it skips the dependency resolution step that often causes the problem.

Add retry logic in your CI configuration:

# GitHub Actions example
- name: Install dependencies
  run: |
    for i in 1 2 3; do
      npm ci && break || {
        echo "npm ci failed, attempt $i/3"
        npm cache clean --force
        sleep 10
      }
    done

Increase memory for Node.js if your CI runner has limited RAM:

export NODE_OPTIONS="--max-old-space-size=4096"
npm ci

Cache node_modules between CI runs to reduce network dependency. Most CI platforms have built-in caching mechanisms:

# GitHub Actions example
- name: Cache node modules
  uses: actions/cache@v4
  with:
    path: ~/.npm
    key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
    restore-keys: |
      ${{ runner.os }}-node-

If your CI builds also fail with exit code errors, the lifecycle-script failure mode is distinct from the cb() class — it shows up as a non-zero exit from a postinstall or prepublish hook rather than a missing callback. Identify the failing script with npm install --verbose and check the package’s GitHub for known platform issues.

Fix 11: Use a Different Package Manager

If nothing else works and you need to move forward, try installing dependencies with a different package manager. Both yarn and pnpm use different caching and resolution mechanisms, which often sidestep whatever is causing npm’s callback failure.

Try Yarn:

# Install Yarn
npm install -g yarn

# Install dependencies
yarn install

Try pnpm:

# Install pnpm
npm install -g pnpm

# Install dependencies
pnpm install

You don’t have to permanently switch your project to a different package manager. This is a diagnostic step — if yarn or pnpm installs successfully, it confirms the problem is specific to npm’s internal handling rather than your packages or network. You can continue using the resulting node_modules while you investigate the npm issue further.

Fix 12: Reinstall Node.js Completely

If you have tried everything above and the error persists across multiple projects, the problem may be with your Node.js and npm installation itself.

On macOS/Linux with nvm:

# List installed versions
nvm ls

# Uninstall the problematic version
nvm uninstall 18.17.0

# Install fresh
nvm install 18
nvm use 18

On Windows:

  1. Uninstall Node.js from “Add or Remove Programs”
  2. Delete the following directories if they exist:
    • C:\Users\<your-user>\AppData\Roaming\npm
    • C:\Users\<your-user>\AppData\Roaming\npm-cache
    • C:\Users\<your-user>\.npmrc (if present and you don’t have custom settings you need)
  3. Download and install Node.js fresh from nodejs.org

On Linux without nvm:

# Remove existing installation
sudo apt-get purge nodejs npm
sudo rm -rf /usr/local/lib/node_modules
sudo rm -rf ~/.npm

# Install fresh using NodeSource
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt-get install -y nodejs

After a fresh install, verify both versions and test with a clean project:

node --version
npm --version
mkdir /tmp/test-npm && cd /tmp/test-npm
npm init -y
npm install express

If this simple install works, the issue is project-specific. If it still fails, the problem is environmental (network, permissions, disk).

Still Not Working?

  1. Read the debug log. The error output includes a path to a log file (e.g., ~/.npm/_logs/2026-06-06T12_00_00_000Z-debug-0.log). Open this file — it contains the full trace of what npm was doing when it failed. Look for network errors, permission denied messages, or specific package names that failed to download.

  2. Run npm with verbose logging:

    npm install --verbose

    This prints every HTTP request, cache lookup, and file operation in real time. Watch for where it stalls or errors out.

  3. Test with a minimal project. Create an empty directory, run npm init -y, and try installing a single package. If that works, the problem is specific to your project’s dependency tree. If it fails, the problem is environmental.

  4. Check for antivirus interference. On Windows, antivirus software (including Windows Defender) can lock files that npm is trying to write, causing the callback to never complete. Try temporarily disabling real-time scanning and retrying the install.

  5. Check if npm scripts are hanging. If a package has a postinstall script that hangs (waiting for input, stuck in an infinite loop, or failing silently), npm may report the callback error. Run with --ignore-scripts to test:

    npm install --ignore-scripts

    If this succeeds, one of your dependencies has a problematic install script. You can identify which one by checking npm ls and looking for packages known to have postinstall scripts (native modules like node-sass, sharp, or bcrypt are common culprits). For problems caused specifically by lifecycle script failures, see Fix: npm ERR! code ELIFECYCLE.

  6. Check that the OS clock is correct. npm signs cached package metadata with timestamps, and the npm registry uses HTTPS certificates with strict validity windows. If your system clock drifts more than a few minutes (common after a sleep/wake cycle on laptops, or inside a Docker container with a misconfigured timezone), HTTPS handshakes succeed but cache validation silently fails. Run date and confirm it matches reality, then sync with sudo ntpdate pool.ntp.org (Linux), sudo sntp -sS time.apple.com (macOS), or w32tm /resync (Windows).

  7. Check ~/.npmrc for stale settings. A stale ~/.npmrc from a years-old corporate setup is a frequent silent saboteur. Look for cafile=, cert=, key=, _authToken=, or registry= pointing at a no-longer-reachable host. Move the file aside and retry:

    mv ~/.npmrc ~/.npmrc.backup
    npm install

    If the install succeeds, copy back only the lines you actually need. Project-level .npmrc (in the same directory as package.json) overrides the user-level file and is often committed to the repo — check it too.

  8. Disable script optimizations on Apple Silicon. Some packages probe the CPU at install time using Node’s os.cpus() and run differently on arm64 versus x86_64. If the probe is buggy, the install hangs. Force the install to run under Rosetta with arch -x86_64 npm install as a diagnostic. If it succeeds, the failing package needs an upgrade for native arm64 support.


Related: If npm installs succeed but you get module resolution errors afterward, see Fix: Error Cannot find module. If you are hitting dependency tree conflicts instead, see Fix: npm ERESOLVE unable to resolve dependency tree. For the global-install permission failures often confused with this error, see Fix: EACCES permission denied when installing npm packages globally.

F

FixDevs

Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.

Was this article helpful?

Related Articles