Diagnose the npm install timeout before changing Clash
An npm install timeout does not automatically mean the npm registry is down—or that your Clash proxy is broken. A package installation can involve several separate requests: npm checks package metadata, downloads one or more tarballs, follows redirects, and may run lifecycle scripts that contact other services. A stalled progress bar can therefore come from a slow route, a proxy setting npm never uses, DNS trouble, an unhealthy Node.js installation, or a package-specific script. Start by recording the exact error and the command that produced it. ETIMEDOUT, ECONNRESET, ECONNREFUSED, and certificate errors point to different layers; treating them as interchangeable often leads to unnecessary registry changes.
First, retry once with npm’s more detailed output and a reasonable timeout. Avoid repeatedly launching installs while the first process is still running, because overlapping requests make the network logs harder to interpret and can leave confusing partial state in the project. Note whether the command fails while fetching metadata, downloading a tarball, or running a script. If only one package fails, compare its name and version with a small package that you know is available. If every package hangs, check the shared path first: DNS, the active Clash profile, local proxy listeners, and npm’s proxy configuration.
npm install --verbose
npm ping
npm config get registry
node --version
npm --version
These checks establish different facts. npm ping tests whether npm can reach the configured registry, but a successful ping does not prove that every package tarball or lifecycle-script host is reachable. The registry setting shows which endpoint npm is actually using; a project, user, or environment setting may override the registry you expected. Node and npm version output helps identify a stale runtime or a version-specific issue. Save the original output before making changes, especially on a work machine where proxy settings may be centrally managed.
Also check the basic local conditions before blaming a remote route. Confirm that the system clock is correct, that the network is not waiting for a hotel or campus captive portal, and that no disk-space or permission error is being mistaken for a network stall. If the same command works on another network without changing the project, record that comparison: it suggests a path or policy difference, but does not by itself identify which rule or hop is responsible.
Check Clash proxy mode, listeners, and Node.js health
Clash can be connected while the terminal still bypasses it. In system-proxy mode, a desktop client typically configures proxy settings for applications that consult the operating system; a terminal process may instead rely on its own environment variables or npm configuration. TUN mode can capture more traffic at the network layer, but it is not a universal cure: routing rules, DNS handling, permissions, and other VPN or security software can still affect the result. Before changing modes, check which mode is active and confirm the local HTTP, HTTPS, or mixed listener port shown by your client.
If you intend npm to use a local HTTP proxy, inspect the shell environment and npm’s own settings. Variable names are case-sensitive on some systems and shells, and values left over from an older VPN can point to a port that is no longer listening. Do not assume that a graphical client’s system-proxy switch exports variables into a terminal that was already open. Open a fresh shell after changing the system proxy, or set the required environment variable only for a controlled test.
npm config get proxy
npm config get https-proxy
npm config get strict-ssl
env | grep -i proxy
On Windows PowerShell, inspect the relevant environment variables with Get-ChildItem Env:*proxy*. On Windows Command Prompt, use set | findstr /i proxy. These commands reveal configured values, so do not paste their output into a public issue without removing any username, password, or private host information. A proxy URL that contains credentials is a secret, even if it is only being used for a temporary test.
Confirm the port shown in Clash is the same one your test uses. For example, if the client reports an HTTP proxy listener on 127.0.0.1:7890, then a request aimed at another port may be refused even though the Clash window says it is running. Do not copy that sample port blindly: ports vary by client, profile, and user configuration. If a local connection is refused, inspect the listener and client logs before changing registry settings. If the request connects but stalls, look further along the route.
Check for competing network layers as well. A corporate VPN, another proxy application, a browser-only extension, or an old system proxy entry can make the browser and npm take different paths. Temporarily disabling managed security software or bypassing workplace controls is not an appropriate troubleshooting step. On a managed device, ask the administrator which proxy endpoint and certificates are required. On a personal device, close duplicate proxy clients during a brief, controlled test and restore your normal setup afterward.
Test the registry route and Clash rules
Once the local listener and npm settings make sense, test the registry from the same terminal that runs npm. A direct request can help separate basic reachability from npm-specific behavior, but it is not a perfect simulation of npm: curl and npm may read different configuration sources and follow requests differently. Compare results rather than treating one successful command as proof that every download path works.
curl -I --max-time 15 https://registry.npmjs.org/
npm ping --fetch-timeout=15000
npm view npm version --fetch-timeout=15000
If curl succeeds but npm ping fails, inspect npm’s registry and proxy configuration, then check for project-level or user-level .npmrc entries. If both fail, verify the current Clash mode, local listener, DNS resolution, and the selected route. If the ping succeeds but installing a particular package fails, look at the verbose log for the exact URL that timed out. The metadata request and the tarball request may not be identical, and a package’s install script can introduce yet another host.
In Clash, use the connection or log view to find the destination host and the rule that matched it. Do not guess from the package name: a package called “example-tool” does not necessarily download from a domain containing that name. Compare the timestamp in Clash with the timestamp of the npm error, then check whether the request was sent to the intended proxy group or went DIRECT. A mismatch between the terminal test and the logged connection is a useful clue that another process, a different host, or an unexpected configuration is involved.
If an applicable rule is missing, make the narrowest reasonable correction in the active profile or rule override. A targeted rule for a verified registry hostname is easier to review and undo than sending every domain through a new policy. Keep it above broad catch-all rules so it can take effect, and confirm that the rule is valid for the core and client you are using. Do not add speculative CDN domains just because a timeout occurred; first identify the destination from the npm log or Clash connection record. After the edit, reload the profile if required and repeat the same test.
Run a controlled npm proxy test and undo it safely
The most useful test changes one variable at a time. First record the current npm proxy values and registry. Then, if your policy permits and you have confirmed the local listener, set a temporary proxy for the current shell rather than changing system-wide configuration. This lets you test whether npm can complete a registry request through the intended Clash listener without making a lasting change to every application on the machine.
In a POSIX-style shell, a one-command environment override can make the scope explicit. Substitute the listener address and port shown by your own Clash client; the example is not a promise that every installation uses port 7890. Run a small metadata request first, then retry the original installation only if the test succeeds. Keep the proxy value free of credentials where possible, and never put a password directly into a command that may be retained in shell history.
HTTPS_PROXY=http://127.0.0.1:7890 HTTP_PROXY=http://127.0.0.1:7890 \
npm view npm version --fetch-timeout=15000
On PowerShell, set variables for the current session and remove them when the test is complete. This does not overwrite the system’s persistent proxy configuration, but it does affect commands launched from that same shell until the variables are removed. If your listener is SOCKS rather than HTTP, do not simply change the URL scheme and assume npm supports it in the same way; use a compatible local HTTP listener or follow the client and npm documentation for your exact setup.
$env:HTTPS_PROXY = "http://127.0.0.1:7890"
$env:HTTP_PROXY = "http://127.0.0.1:7890"
npm view npm version --fetch-timeout=15000
Remove-Item Env:HTTPS_PROXY
Remove-Item Env:HTTP_PROXY
If the controlled test works, compare it with the original shell state. That points toward a missing or stale npm proxy setting, rather than proving that all future installs need a global proxy. If it still fails, remove the temporary variables and inspect the request in Clash. A connection that never reaches the local listener suggests a shell or application configuration issue; a connection recorded by Clash but routed through an unexpected group points toward rules or mode; a connection that uses the expected route but times out may require checking the selected node, remote endpoint, or network policy.
Avoid changing several settings at once. Switching to a different registry, changing DNS, clearing npm’s cache, and replacing the Clash profile in one attempt destroys the comparison that would tell you which change mattered. A registry mirror can also have different availability, package freshness, authentication requirements, or policy implications. Use a mirror only if it is trusted and permitted in your environment, and write down the original registry so you can restore it.
Interpret the result and restore the original state
Read the final error together with the verbose log and the Clash connection record. ECONNREFUSED commonly means that a connection was rejected, often because a local proxy listener is unavailable or the target refused the connection. ETIMEDOUT means the connection did not complete within the expected period; it can occur on the local path or farther away. ECONNRESET indicates that a connection was reset after it began. Certificate or TLS errors call for checking the system clock, Node’s certificate store, and any organization-approved TLS inspection configuration—not turning off certificate verification as a quick fix.
If you changed npm’s persistent settings during diagnosis, restore their recorded values. When a setting did not previously exist, remove it rather than replacing it with a guessed default. For example, after a temporary persistent proxy test, npm config delete proxy and npm config delete https-proxy remove those keys from the configuration level npm resolves for the command. Check again with npm config get proxy and npm config get https-proxy; if a project or environment variable still supplies a value, locate and correct that source instead of repeatedly editing the user configuration.
Cache cleanup is not the first remedy for a network timeout. npm’s cache is designed to be resilient, and deleting it cannot repair a route that never reaches the registry. Consider cache verification only when the logs suggest corrupted or inconsistent cached content, and preserve project lockfiles so that a retry does not silently change dependency versions. For shared projects, record the Node.js and npm versions, registry, operating system, and the failing host when reporting the issue; those details are more useful than an unredacted dump of the entire environment.
A reliable resolution is one you can reproduce and reverse: the same npm request succeeds through the intended route, the Clash log shows the expected policy decision, and unrelated traffic still follows its normal rules. Compared with a browser-only proxy extension, Clash can make the terminal’s route visible in connection logs and apply deliberate rules beyond one browser; compared with a global VPN toggle, a narrowly checked rule can make the destination and policy easier to audit. If your current client makes listener status, routing decisions, or profile changes difficult to verify, Clash V.CORE offers a clearer place to inspect those settings while you troubleshoot. Once you have confirmed that it fits your device and network policy, you can download Clash V.CORE and repeat the checks with your own registry and listener details.
// Editor's Pick
Make npm routing easier to verify
Inspect the active proxy path, confirm rule decisions, and troubleshoot npm registry timeouts without guessing which layer is responsible.
- Review active proxy mode and local listeners
- Check routing decisions for registry connections
- Keep targeted rule changes visible and reversible
- Compare direct and proxied terminal tests