Magic Tools
Hands-OnBy CooconAugust 7, 2026370 views2 min read

claude install Creates a Broken %h Symlink? Clean Debian Test Comes Out Fine (Not Reproduced)

What this article is: a not-reproduced field report. We could not reproduce the reported problem — which does not mean the report is wrong, only that it does not show up in the environment and with the method below. Every command and its raw output is included; cross-check us.

What the original report says

GitHub issue #83484 (Fedora 44 + bash, Claude Code 2.1.220): after running the official one-line installer, ~/.local/bin/claude is a broken symlink —

$ curl -fsSL https://claude.ai/install.sh | bash
$ file ~/.local/bin/claude
/home/user/.local/bin/claude: broken symbolic link to %h/.local/share/claude/versions/2.1.220

The %h in the target is an unexpanded placeholder (the systemd-style home-directory specifier) that should have become /home/user. The reporter traced the problem not to the shell installer but to the binary's internal install subcommand, and confirmed it is a regression ("this worked in a previous version"). The issue links a fix PR (#83738, unmerged at reporting time).

Our test: it comes out fine

Environment: a clean debian:bookworm-slim Docker container, root user, 2026-08-06, running the exact command from the report:

$ curl -fsSL https://claude.ai/install.sh | bash
$ ls -la /root/.local/bin/claude
lrwxrwxrwx 1 root root 42 Aug  6 10:23 /root/.local/bin/claude -> /root/.local/share/claude/versions/2.1.223
$ file /root/.local/bin/claude
/root/.local/bin/claude: symbolic link to /root/.local/share/claude/versions/2.1.223

Two key observations:

  1. The symlink is valid — the home directory in the target path expanded correctly to /root, with no literal %h anywhere
  2. install.sh currently ships 2.1.223, three releases past the reported 2.1.220 (2.1.221/222/223 released August 3/4/5)

Why it did not reproduce: three candidate explanations

Ordered by strength of evidence:

Explanation 1: fixed somewhere in 2.1.221–2.1.223 (most likely). The report was against 2.1.220, a fix PR exists, and install.sh now ships 2.1.223 — if the fix landed in any of those releases, fresh installs simply no longer hit it. We could not find release notes explicitly saying "fixed %h expansion", so this remains unconfirmed.

Explanation 2: distro-specific. The report is from Fedora 44; we tested Debian 12. %h is the home-directory specifier used in systemd unit files — if the binary's install subcommand reads a path template from systemd-related configuration on some systems, behavior could vary by distro. This is a mechanism guess; we have no Fedora environment to verify it.

Explanation 3: leftover state in the reporter's environment. The reporter said a previous version worked, so remnants of the older install may have participated in path generation. A clean container has no remnants — which might be exactly why we cannot trigger it. Equally unconfirmed.

Whatever the root cause, the repair is deterministic (the workaround the reporter verified in the issue):

# Point the broken link at the version directory that actually exists
ls ~/.local/share/claude/versions/        # see what versions you have
ln -sf ~/.local/share/claude/versions/<version> ~/.local/bin/claude
claude --version                          # verify

Or simpler: re-run the official install command — the 2.1.223 it currently ships came out clean in our test.

Scope and boundaries

  • This article proves only: a clean Debian 12 environment + the 2026-08-06 install.sh (shipping 2.1.223) does not exhibit the problem
  • It does not prove: that Fedora is fixed, that the 2.1.220 problem never existed, or that every environment is fine
  • If you can still reproduce it on another distro (especially Fedora with 2.1.221+), please add your environment details to issue #83484 — that would directly falsify explanation 1 and substantiate explanation 2

Get field notes like this every Saturday

Subscribe to Dev Breakfast: daily AI coding picks at 8:00, plus a Saturday roundup of this week's hands-on tests with Claude Code / Codex / local models. Written in Chinese.

Related Articles

Claude Code "Prompt is too long" vs "maximum context length": Why Auto-Compact Works for One and Not the Other (Tested)

Claude Code decides a request was too long by matching the error text. If the backend says prompt is too long or input is too long for requested model, it auto-compacts the conversation and retries — invisible to you. DeepSeek and OpenAI-style gateways say This model's maximum context length is …, which it doesn't recognize: you get API Error: 400 on every turn. Manual /compact works; the better fix is to declare the real window with CLAUDE_CODE_MAX_CONTEXT_TOKENS (non-claude- model IDs) or CLAUDE_CODE_AUTO_COMPACT_WINDOW (claude- IDs) so it compacts before hitting the limit. Tested on Claude Code 2.1.285 against a local stub.

claude-codedeepseek+6
pitfallsOct 5, 20267 min
122

Claude Code Stuck on a Spinner With No Response: It Waits 6 Minutes per Attempt, and 10 Retries Can Hang It for Over an Hour (Tested)

When Claude Code spins without output or sits at Retrying in 0s, the backend is usually not sending anything. Tested on 2.1.285 (API key + ANTHROPIC_BASE_URL): with no response headers it waits 6 minutes (360 s) per attempt before timing out — setting API_TIMEOUT_MS to 600000 or 900000 doesn't change that; only lower values work. With the default 10 retries it can hang for over an hour. A gateway that buffers the reply until generation finishes will never deliver a reply that takes over 6 minutes. Press Esc to interrupt. All tested against a local stub.

claude-codetroubleshooting+5
pitfallsOct 5, 20269 min
102

Claude Code 429 "Request rejected (429)": How Long It Retries, and Why retry-after Over 60 Seconds Fails Instantly (Tested)

On a 429, Claude Code retries up to 10 times over about 3 minutes. If retry-after is 60 seconds or less it waits the full time (10 s and 60 s both recovered in testing); at 61 seconds or more it does not retry at all and fails immediately with API Error: Request rejected (429). Gateway messages such as new-api's are shown verbatim; an empty body shows status code (no body). In interactive mode every prompt sends 2 requests, so rate-limit usage doubles. All tested against a local stub on Claude Code 2.1.285.

claude-codetroubleshooting+4
pitfallsOct 4, 20268 min
99
Claude Code MCP Shows Connected but 0 Tools: "Invalid result for tools/list" (ttlMs / cacheScope), Reproduced and Fixed

Claude Code MCP Shows Connected but 0 Tools: "Invalid result for tools/list" (ttlMs / cacheScope), Reproduced and Fixed

An MCP server shows as connected but exposes 0 tools, and the log says Invalid result for tools/list with ttlMs and cacheScope failing validation. Reproduced with a stub server on Claude Code 2.1.280, 2.1.285 and 2.1.288: the cause is not extra fields being rejected. The server negotiated MCP 2026-07-28 and then left out fields that revision requires (resultType, ttlMs, cacheScope); adding unknown fields works fine. Whether stdio uses the new protocol is decided by a remote flag that is off by default, so the same version breaks for some users and not others, and 2.1.280 fails the same way once negotiation is on. MCP_PROTOCOL_NEGOTIATION=legacy (also works in settings.json env) restores the tools; servers fix it by adding the three fields.

mcpclaude-code+4
pitfallsOct 3, 20268 min
92