Installation failed Failed to fetch version from stable: AxiosError: timeout of 30000ms exceeded
Nothing was installed and nothing was written to disk. The installer asked which
version the stable channel currently points at, waited out its full HTTP
timeout, and gave up before any package was downloaded. That rules out most of
what people check first: it is not a permissions problem, not a full disk, not a
corrupt package, and not your API key or plan — no credentials are involved in
reading a version number.
Data as of 2026-09. Vendor limits and defaults change; check the official docs for current values before acting on any number below.
A timeout is a different failure from “cannot connect”
This is the distinction that decides everything downstream, and the error string hands it to you for free.
If DNS had failed you would see a resolution error. If nothing were listening you would get a connection refused, immediately. If a proxy were intercepting TLS with a certificate your machine does not trust, you would get a certificate error, also immediately. A timeout means the request went out and nothing came back at all — the signature of something that drops traffic silently rather than rejecting it. Corporate firewalls do that. Egress allowlists in CI do that. A proxy that requires authentication for an unknown destination does that. A captive portal does that.
So “my internet works fine” is not evidence of anything here. Your browser is going through a proxy that is configured for it. The installer is a different program with a different configuration, and it is being blackholed on a path your browser never takes.
The setting people are sure they already fixed
Here is the trap that costs the most time. Teams behind a proxy configure npm —
npm config set proxy, npm config set https-proxy, or an .npmrc handed down
by IT — and reasonably assume the whole install honors it.
An axios-based HTTP client in Node reads the standard proxy environment
variables (HTTP_PROXY, HTTPS_PROXY, NO_PROXY). It does not read .npmrc.
npm’s proxy configuration applies to npm’s own requests. A version lookup made
by the installer’s own HTTP client is not one of npm’s requests.
That is why the tell-tale state exists at all: npm ping succeeds, npm install
of anything else succeeds, and this one fetch stalls for the full timeout. Two
HTTP clients, two configurations, one network that only tolerates the configured
one.
The same split explains why the install sometimes behaves differently under
sudo or inside a CI job. Elevated and non-interactive environments do not
inherit your login shell’s environment by default, so the proxy variables you
exported are simply not there when it matters.
Is retrying useful?
No — not until you have changed something.
Every attempt costs you the full 30-second stall before it reports anything, and a path that drops packets will drop them again. You almost certainly already pressed up-arrow and Enter once before you searched for this message; that was the experiment, and it came back negative.
Treat a second identical failure as the diagnosis it is: deterministic, path- level, and fixable only by changing the client’s configuration or the route it takes. If the failure is intermittent — succeeding maybe one attempt in three — that is a different signal, pointing at a flaky resolver or a rate-limited egress proxy rather than a hard block, and it is worth capturing which attempts succeed. It is still not a reason to sit there retrying.
Working out who is dropping the traffic
Check the environment that actually runs the installer, not your shell. Run
env | grep -i proxy in the exact context you install from — inside the
container, inside the CI job, in the elevated shell if you used one. Variables
present in your interactive shell and absent there is the single most common
finding.
Test plain HTTPS egress from that same context. curl -v any HTTPS endpoint
you are allowed to reach. If curl works and the installer stalls, the network is
not the problem — the installer’s client configuration is. If curl hangs too,
the block is on the path, and no client-side setting will get you through it.
Get the hostname the installer is asking for. Run the install with whatever verbose or debug output it supports and read which host it is trying to reach, then test that host specifically. An allowlist that permits the npm registry but not a release-metadata host produces exactly this error, and you cannot guess your way to that finding.
Check NO_PROXY for over-reach. A NO_PROXY entry broad enough to cover
the destination sends the request direct, past the only route out of the
network. This looks identical to having no proxy configured at all.
Try from outside the restricted network once. A phone hotspot or a machine off the VPN takes ninety seconds and cleanly separates “my environment blocks this” from “the endpoint is unreachable for everyone”.
Fixes, matched to what the tests showed
Proxy required, variables missing in that context — export HTTPS_PROXY,
HTTP_PROXY and an accurate NO_PROXY in the environment that runs the
installer. In CI, set them in the job definition rather than a shell profile.
If you were installing under elevation, prefer installing as the user who owns
the install directory instead — that is also what the
auto-update failure page
is about, and doing it that way removes two problems at once.
Egress allowlist in a container or CI — get the host from the verbose output and have it allowlisted. The durable version of this fix is mirroring the artifacts you depend on into a registry you control and installing from there, so a build is not one firewall rule away from failing.
Traffic silently dropped with no proxy available — this is a policy decision on your network, not a bug you can configure around. Install from a network that permits it, or ask for the exception.
Genuinely slow link — the timeout belongs to the installer’s HTTP client,
not to you. No knob for it is published in the official install documentation;
check code.claude.com before assuming one exists, and do not copy a
“just raise the timeout” incantation from a forum post that invented it.
Certificate errors instead of a timeout — different class entirely. A TLS interception failure is a trust-store problem, and a timeout during an OAuth exchange is a third thing again: that one happens after the tool is installed and is about a login round-trip, not a release channel.
How you know it is fixed
Re-run the identical install command in the identical environment — same container image, same CI job definition, same shell — and watch the timing. A real fix returns promptly. If the command still pauses for a long beat before succeeding, something is still falling back and you have fixed it by luck.
Then run it a second time from a cold start: a fresh container or a fresh job, not the warm shell you have been experimenting in. Half of the “fixes” for this error are environment variables that live only in the terminal where they were typed, and a cold run is the only thing that catches that.
After the install completes, claude --version should print. If it prints but a
later launch dies on a version string, you have moved on to
a semver parse failure, which is unrelated to
the network. If you are unsure which install-time failure you are looking at,
the AI coding error triage tool sorts them by
how far the process got before it stopped.