npm install Hangs? A Systematic Troubleshooting Guide
When npm install appears frozen, repeatedly restarting it usually hides the useful evidence. The delay is commonly caused by network access, proxy configuration, dependency resolution, a lifecycle script, native compilation, cache damage, or a Node.js version mismatch.
1. Capture detailed logs
Run the install with verbose output:
npm install --verbose
Also record the active toolchain and configuration:
node --version
npm --version
npm config get registry
npm config list
A line such as idealTree:userRequests describes the dependency-resolution stage; it is not the root cause by itself. Inspect the requests and messages immediately before and after it.
2. Test registry and DNS access
Verify that npm can reach the registry:
npm ping
npm view lodash version
curl -I https://registry.npmjs.org/
If these commands are slow, check DNS, VPN, firewall, corporate TLS inspection, and proxy settings. Review both npm-specific and environment proxies:
npm config get proxy
npm config get https-proxy
env | grep -i proxy
Remove stale npm proxy values when they are no longer required:
npm config delete proxy
npm config delete https-proxy
Do not disable TLS verification as a permanent workaround. Install the correct organization CA certificate instead.
3. Verify the cache
Use npm's built-in verification first:
npm cache verify
Cache deletion should be a targeted experiment, not the default first step. If verification reports corruption and you have ruled out network problems, use:
npm cache clean --force
4. Separate dependency resolution from scripts
Packages may run preinstall, install, or postinstall scripts that download binaries or compile native modules. Test without scripts:
npm install --ignore-scripts
If that completes, inspect lifecycle scripts and rerun the relevant one with foreground output:
npm install --foreground-scripts --verbose
Native builds may require Python, a C/C++ toolchain, and platform development headers.
5. Check the lockfile and Node version
For CI and reproducible installs, prefer:
npm ci
It requires package.json and package-lock.json to agree. Do not delete a committed lockfile casually; doing so changes the resolved dependency graph. Confirm the project's supported Node version through .nvmrc, .node-version, the engines field, or project documentation.
6. Find the slow package
Useful experiments include:
npm install --timing
npm explain package-name
npm ls
Check the npm debug log path printed by the failed command. Git-based dependencies may be waiting on SSH credentials, inaccessible hosts, or Git LFS. Browser automation packages often download large binaries and can be blocked by proxies.
A reliable cleanup sequence
After preserving the original error, a controlled local retry is:
rm -rf node_modules
npm cache verify
npm ci --verbose
Keep the lockfile unless you intentionally want to update dependencies. In CI, add explicit timeouts and cache keys based on the lockfile so a stalled registry request cannot block a runner indefinitely.