Skip to content

fix(agent): re-run install.cjs after npm update in Dockerfile#613

Open
fibanez wants to merge 1 commit into
aws-samples:mainfrom
fibanez:fix/agent-claude-binary-postinstall
Open

fix(agent): re-run install.cjs after npm update in Dockerfile#613
fibanez wants to merge 1 commit into
aws-samples:mainfrom
fibanez:fix/agent-claude-binary-postinstall

Conversation

@fibanez

@fibanez fibanez commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Claude Code 2.1.x ships as a native binary installed via a postinstall script (install.cjs) that hardlinks the platform-specific binary over a placeholder stub at bin/claude.exe.
  • In the agent Dockerfile, the npm --prefix update step (which patches vulnerable transitive deps inside the global @anthropic-ai/claude-code install) re-extracts the package's bin entry, overwriting the native binary with the stub script. npm does not re-run postinstall during update, so the binary is never restored.
  • At runtime in AgentCore, the container tries to exec the stub (a shell script, not an ELF binary), producing: OSError: [Errno 8] Exec format error: 'claude'
  • Fix: append node "${CLAUDE_NPM_ROOT}/install.cjs" to the Dockerfile's npm install layer so the native binary is re-placed after the update step.

Test plan

  • Built image locally and verified claude --version returns 2.1.191 (Claude Code)
  • Deployed to backgroundagent-dev stack in us-west-2
  • Submitted a task and confirmed it completes without exec format error

@fibanez fibanez requested review from a team as code owners July 15, 2026 19:30
Claude Code 2.1.x ships native binaries via postinstall. The npm update
step that patches transitive deps overwrites bin/claude.exe back to the
fallback stub, causing 'Exec format error' at runtime.

Re-run install.cjs to restore the native binary after the update.
@fibanez fibanez force-pushed the fix/agent-claude-binary-postinstall branch from f5c59dd to 0190103 Compare July 15, 2026 19:32
@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
⚠️ Please upload report for BASE (main@22705e8). Learn more about missing BASE report.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #613   +/-   ##
=======================================
  Coverage        ?   89.30%           
=======================================
  Files           ?      224           
  Lines           ?    54356           
  Branches        ?     5719           
=======================================
  Hits            ?    48544           
  Misses          ?     5812           
  Partials        ?        0           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@isadeks isadeks left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review — and yes, this overlaps with two other open PRs

The fix itself is correct: npm update re-extracts the package's bin entry over the placeholder stub and npm doesn't re-run postinstall on update, so appending node install.cjs restores the native binary. Diagnosis matches main's Dockerfile exactly, CI is green, and it's a minimal 2-line change. I verified install.cjs exists in @anthropic-ai/claude-code@2.1.191 and is idempotent (re-running it when the binary is already correct is harmless). One caveat on my verification: on linux/amd64 I couldn't reproduce the npm update clobber (the binary stayed ELF) — the clobber looks arch-specific to the arm64 AgentCore image, which matches both this PR and #597 reporting it as live-caught on the deployed image, so I can't independently confirm the failure trigger, only that the fix is safe.

The overlap you'd want to resolve before merging any of these — three open PRs touch this exact issue:

PR Layer Exec-format handling
#613 (this) agent/Dockerfile + node install.cjs
#597 agent/Dockerfile + more + node install.cjs && claude --version
#599 error-classifier.ts adds the pattern that labels the runtime error
  • #597 is a strict superset of this PR on the Dockerfile line — it adds the identical install.cjs step plus && claude --version, which hard-gates the image build (a broken shim fails docker build, instead of every task dying at runtime). That build-time assertion is strictly better than restoring-and-hoping. #597 also carries a code comment explaining the shim mechanism.
  • #613 and #597 edit the same RUN … npm --prefix update … line, so they will textually conflict — both can't merge as-is.
  • #599 is complementary, not a conflict — it classifies the same Exec format error into a user-facing "Couldn't start the coding agent (environment issue)" (disjoint file). Prevention (#613/#597) + legibility (#599) are the two halves of ABCA-659; ideally both land.

Recommendation: fold this into #597's version (the && claude --version hard-gate) rather than merging #613 separately, then close #613 as superseded — unless #597 is blocked by its stack (it's stacked on #596#503; #503 merged, #596 still open). If #597 is going to sit behind that stack for a while and the exec-format break is hurting people now, the pragmatic call is to merge this (it's clean against main) and have #597 drop its Dockerfile hunk on rebase. Either way, please add the && claude --version build-time gate here so a future silent postinstall fallback fails the build, not the fleet — that's the one substantive thing #597 has that this doesn't.

(Flagging the overlap rather than re-reviewing the mechanics of all three; happy to review #597 in full — it also has a build-timeout classifier + failing-line log surfacing worth a look.)

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.

3 participants