Skip to content

fix: propagate curl exit code through pipe with set -o pipefail#1159

Open
qozle wants to merge 1 commit intoanthropics:mainfrom
qozle:fix/curl-pipefail-install
Open

fix: propagate curl exit code through pipe with set -o pipefail#1159
qozle wants to merge 1 commit intoanthropics:mainfrom
qozle:fix/curl-pipefail-install

Conversation

@qozle
Copy link
Copy Markdown
Contributor

@qozle qozle commented Apr 4, 2026

Problem

installClaudeCode() runs a bash command that pipes the install script output.

Because of POSIX pipe semantics, the exit code of this pipeline is the exit code of the last command (bash), not curl. When curl returns HTTP 429 (rate-limited) or 403 (auth error), it exits non-zero — but bash receives an empty or partial script and exits 0. The caller sees success, the retry loop never fires, and Claude Code is not actually installed.

Fix

Four targeted changes to installClaudeCode() in src/entrypoints/run.ts:

  1. set -o pipefail — prefixed to the bash command so any non-zero exit anywhere in the pipeline propagates to the process exit code. Curl 429/403 now correctly fails the install attempt.

  2. Version regex guard — validate claudeCodeVersion against /^\d+\.\d+\.\d+$/ before interpolating into the shell command. The version is currently hardcoded so injection is not possible today, but this guards against future refactors that make it configurable.

  3. Post-install binary check — after a successful spawn exit, verify existsSync(homeBin + '/claude'). Even with pipefail, a network drop mid-transfer after bash has started could produce a truncated script that exits 0. The binary check catches that.

  4. Better retry logging — log the actual error on failed attempts (not just "Installation failed, retrying..."), so CI logs show what actually went wrong.

Changes

  • homeBin hoisted above the loop (was inside the success block; now shared with the binary check and PATH append)
  • No temp files, no new imports (existsSync already imported at line 9)

Fixes #1136

When curl returns 429/403, the install silently succeeds because
POSIX pipe exit = last command (bash), not curl. The 3-attempt retry
loop never fired on rate-limit or auth errors.

Changes:
- Prefix bash command with set -o pipefail to propagate curl errors
- Validate claudeCodeVersion format before interpolating into shell
- Hoist homeBin above loop; verify binary exists post-install
- Log the actual error on failed attempts instead of generic message

Fixes anthropics#1136

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Install silently fails on curl 429/403 due to missing pipefail in curl|bash pipeline

1 participant