[BUG] Auto-update silently exits 0 when native optional dependency download is throttled — leaves stub binary + no bin symlink → "command not found"

Open 💬 0 comments Opened Jul 1, 2026 by AfonsoZhang

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

On a slow/throttled connection to registry.npmjs.org, npm install @anthropic-ai/claude-code@latest
(what the auto-updater runs) fails to download the large platform-native optional dependency,
yet exits 0 reporting success. The result is a broken install: bin/claude.exe is left as the
500-byte fallback stub, and the bin/claude symlink is never created — so the next launch fails with
claude: command not found. The user gets no error at update time; the update "succeeds" silently.

This is distinct from the Rosetta/arch case (#50974) and the Bun case (#50203): here the correct
platform package IS resolved, it just never finishes downloading, and because it's an optional
dependency npm drops it without failing the install.

What Should Happen?

When the native binary can't be obtained, the install/update should fail loudly (non-zero exit),
or the updater should verify bin/claude.exe is a real executable before declaring success —
never leave a silently-broken install that only surfaces at next launch.

Error Messages/Logs

77 silly tarball no local data for @anthropic-ai/claude-code-linux-x64@...tgz. Extracting by manifest.
78 verbose reify failed optional dependency .../@anthropic-ai/claude-code-linux-x64
79 silly reify mark deleted [ '.../@anthropic-ai/claude-code-linux-x64' ]
80 info run @anthropic-ai/claude-code@2.1.197 postinstall ... node install.cjs
95 verbose exit 0
96 info ok

Resulting state: `file bin/claude.exe` -> `ASCII text` (the stub, not an ELF); `~/.npm-global/bin/claude` missing.

Steps to Reproduce

The underlying mechanism is generic npm behavior (optional-dependency tarball fetch times out →
npm silently drops it and still exits 0), combined with install.cjs never validating that the
binary it wrote is real. Part A reproduces the npm mechanism deterministically in under a minute
with no special network conditions required. Part B is what actually happened with claude-code.

Part A — minimal, deterministic repro of the npm mechanism (no slow network needed)

  1. Create a tiny "slow" package and serve it locally with an artificial delay:

``bash
mkdir -p /tmp/repro/pkg && cd /tmp/repro/pkg
npm init -y -s >/dev/null && echo "module.exports = 1;" > index.js
npm pack >/dev/null # -> pkg-1.0.0.tgz
cd /tmp/repro
python3 -c "
import http.server, socketserver, time
class SlowHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
if self.path.endswith('.tgz'):
time.sleep(5) # simulate a stalled/throttled download
return super().do_GET()
with socketserver.TCPServer(('127.0.0.1', 8899), SlowHandler) as httpd:
httpd.serve_forever()
" &
``

  1. Create a consumer package that depends on it as an optional dependency via a direct tarball URL:

``bash
mkdir -p /tmp/repro/consumer && cd /tmp/repro/consumer
cat > package.json <<'EOF'
{
"name": "consumer",
"version": "1.0.0",
"optionalDependencies": {
"slow-pkg": "http://127.0.0.1:8899/pkg/pkg-1.0.0.tgz"
}
}
EOF
``

  1. Force a short fetch timeout so the 5s artificial delay triggers the same failure npm hits on a

throttled real connection (on a genuinely slow link this happens naturally at the default timeout,
~5 min, without needing this flag):
``bash
npm install --fetch-timeout=2000
echo "exit code: $?"
``

  1. Observe: exit code: 0, but node_modules/slow-pkg does not exist — npm silently dropped the

optional dependency and reported success anyway. This is the exact mechanism hitting
@anthropic-ai/claude-code-linux-x64 in Part B.

Part B — what actually happened with claude-code (2.1.197)

  1. On a machine with a normal-looking but throttled path to registry.npmjs.org for large payloads

(small metadata requests fine, ~35 KB/s for large tarballs — confirmed via curl -w '%{speed_download}'),
let the built-in auto-updater run, or trigger it manually:
``bash
npm install -g @anthropic-ai/claude-code@latest
echo "exit code: $?"
``

  1. Watch ~/.npm/_logs/*-debug-0.log for the latest run — see the "Evidence" block below; note it

ends in verbose exit 0 / info ok despite the optional native package being marked deleted.

  1. Inspect the resulting binary — it's the fallback stub, not the real executable:

``bash
file ~/.npm-global/lib/node_modules/@anthropic-ai/claude-code/bin/claude.exe
# -> ASCII text (expected: ELF 64-bit LSB executable ...)
ls -la ~/.npm-global/bin/claude
# -> No such file or directory (symlink was never (re)created)
``

  1. Launch the CLI:

``bash
claude --version
# -> claude: command not found
``

Claude Model

None

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

2.1.197

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

WSL (Windows Subsystem for Linux)

Additional Information

claude-update-issue.md

View original on GitHub ↗