claude-code image ships a broken native binary when npm's optionalDependencies fetch fails during build #353
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Symptom
A bring-up on
macos-containerfailed with two errors in sequence:Root cause
@anthropic-ai/claude-code@2.1.172distributes its CLI as a native binary pulled in via a platform-specificoptionalDependenciesentry (e.g.@anthropic-ai/claude-code-linux-arm64), not the old JS-shim model.npm install -ginbot_bottle/contrib/claude/Dockerfilehit a transient failure fetching that optional package. npm treats optional-dependency install failures as non-fatal, so the overallnpm install -gstill exited 0, leaving a 500-byte stubbin/claude.exethat only prints "claude native binary not installed" at first invocation.Because the npm-install
RUNlayer is Docker/BuildKit-cached, every subsequentcontainer buildreused the broken cached layer instead of retrying the fetch — the image looked “built successfully” indefinitely until forced to rebuild without cache.container run --rm --entrypoint claude bot-bottle-claude:latest --versionreproduced it directly against the running image;claude.exewas 500 bytes instead of the real ~250MB binary.Fix (see linked PR)
claude --version/ codex's equivalent) inside a throwaway container of the freshly built image and fail loudly instead of shipping a broken image.--no-cacheflag (bot-bottle start --no-cache, alsoBOT_BOTTLE_NO_CACHE=1) to force a from-scratch rebuild when this happens again.Out of scope / follow-up
bot_bottle/contrib/pi/Dockerfileinstalls@earendil-works/pi-coding-agentwith--ignore-scripts, which would guarantee a broken postinstall if that package also ships a native binary this way. Not verified/fixed here — worth checking separately.