fix: use copy package-import-method in Docker to avoid pnpm ENOENT#12100
fix: use copy package-import-method in Docker to avoid pnpm ENOENT#121000xApotheosis merged 3 commits intodevelopfrom
Conversation
pnpm's default hard-link strategy fails intermittently on Docker's overlay filesystem with "ENOENT: rename _tmp -> secp256k1". Setting package-import-method=copy via env var (Docker-only, doesn't affect local dev .npmrc) fixes the atomic rename race condition. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughAdds package import method Changes
Sequence Diagram(s)(omitted — changes are build/setup focused and do not introduce a multi-component runtime control flow requiring a sequence diagram) Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
The ENOENT rename failure persists even with package-import-method=copy because pnpm's hoisting/linking phase still does atomic renames that race on Docker's overlay filesystem. Since it's intermittent and all packages are cached in the store after the first attempt, a retry with clean node_modules is fast and reliable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@packages/swap-widget/Dockerfile`:
- Around line 61-64: The retry loop using "for i in 1 2 3; do ... pnpm install
--frozen-lockfile --ignore-scripts && break || { echo ...; rm -rf node_modules;
}; done" can return success even if all pnpm attempts fail because the cleanup
command (rm -rf node_modules) exits 0; change the failure branch so that a
failed pnpm install yields a non-zero exit on the final attempt (e.g., after
cleaning on failure either return a non-zero status or explicitly exit when
i==3) so the Docker build fails if all retries fail.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 7c02e691-5ee5-4b6b-956b-92caaf000510
📒 Files selected for processing (2)
packages/public-api/Dockerfilepackages/swap-widget/Dockerfile
🚧 Files skipped from review as they are similar to previous changes (1)
- packages/public-api/Dockerfile
| for i in 1 2 3; do \ | ||
| pnpm install --frozen-lockfile --ignore-scripts && break || \ | ||
| { echo "pnpm install attempt $i failed, retrying..."; rm -rf node_modules; }; \ | ||
| done |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# First, let's verify the shell semantics claim from the review
# Test the bad pattern (current implementation)
sh -c 'for i in 1 2 3; do false && break || { rm -rf /tmp/nonexistent; }; done'
echo "bad loop exit=$?"
# Test the good pattern (proposed fix)
sh -c 'for i in 1 2 3; do if false; then break; fi; if [ "$i" -eq 3 ]; then exit 1; fi; done'
echo "good loop exit=$?"Repository: shapeshift/web
Length of output: 90
🏁 Script executed:
# Now let's check the actual Dockerfile to confirm the code matches the review comment
cd packages/swap-widget && cat -n Dockerfile | head -70 | tail -20Repository: shapeshift/web
Length of output: 1302
Retry loop falsely succeeds after three failed installs.
The current retry loop at lines 61-64 can exit successfully even when all pnpm install attempts fail. When pnpm fails on the final iteration, the || clause executes rm -rf node_modules, which exits with code 0, causing the loop to complete without error. This allows Docker builds to succeed despite missing dependencies, risking broken container images being pushed to production.
Proposed fix
RUN corepack enable && corepack prepare pnpm@10.30.3 --activate && \
- for i in 1 2 3; do \
- pnpm install --frozen-lockfile --ignore-scripts && break || \
- { echo "pnpm install attempt $i failed, retrying..."; rm -rf node_modules; }; \
- done
+ for i in 1 2 3; do \
+ if pnpm install --frozen-lockfile --ignore-scripts; then \
+ break; \
+ fi; \
+ if [ "$i" -eq 3 ]; then \
+ echo "pnpm install failed after $i attempts"; \
+ exit 1; \
+ fi; \
+ echo "pnpm install attempt $i failed, retrying..."; \
+ rm -rf node_modules; \
+ done📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| for i in 1 2 3; do \ | |
| pnpm install --frozen-lockfile --ignore-scripts && break || \ | |
| { echo "pnpm install attempt $i failed, retrying..."; rm -rf node_modules; }; \ | |
| done | |
| RUN corepack enable && corepack prepare pnpm@10.30.3 --activate && \ | |
| for i in 1 2 3; do \ | |
| if pnpm install --frozen-lockfile --ignore-scripts; then \ | |
| break; \ | |
| fi; \ | |
| if [ "$i" -eq 3 ]; then \ | |
| echo "pnpm install failed after $i attempts"; \ | |
| exit 1; \ | |
| fi; \ | |
| echo "pnpm install attempt $i failed, retrying..."; \ | |
| rm -rf node_modules; \ | |
| done |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/swap-widget/Dockerfile` around lines 61 - 64, The retry loop using
"for i in 1 2 3; do ... pnpm install --frozen-lockfile --ignore-scripts && break
|| { echo ...; rm -rf node_modules; }; done" can return success even if all pnpm
attempts fail because the cleanup command (rm -rf node_modules) exits 0; change
the failure branch so that a failed pnpm install yields a non-zero exit on the
final attempt (e.g., after cleaning on failure either return a non-zero status
or explicitly exit when i==3) so the Docker build fails if all retries fail.
Without an explicit `types` field, TypeScript auto-discovers all @types/* packages hoisted to root node_modules. The deprecated stub @types/ethereumjs-util (from hdwallet-ledger devDeps) has no .d.ts files, causing TS2688 during Docker builds. Restricting to ["vite/client"] matches the pattern used by the root tsconfig. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…12100) * fix: use copy package-import-method in Docker to avoid pnpm ENOENT pnpm's default hard-link strategy fails intermittently on Docker's overlay filesystem with "ENOENT: rename _tmp -> secp256k1". Setting package-import-method=copy via env var (Docker-only, doesn't affect local dev .npmrc) fixes the atomic rename race condition. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: add retry loop for pnpm install in Docker builds The ENOENT rename failure persists even with package-import-method=copy because pnpm's hoisting/linking phase still does atomic renames that race on Docker's overlay filesystem. Since it's intermittent and all packages are cached in the store after the first attempt, a retry with clean node_modules is fast and reliable. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: restrict swap-widget tsconfig types to prevent auto-discovery Without an explicit `types` field, TypeScript auto-discovers all @types/* packages hoisted to root node_modules. The deprecated stub @types/ethereumjs-util (from hdwallet-ledger devDeps) has no .d.ts files, causing TS2688 during Docker builds. Restricting to ["vite/client"] matches the pattern used by the root tsconfig. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>

Description
Fix intermittent
pnpm installfailure in Docker builds for both public-api and swap-widget:pnpm's default hard-link strategy (
package-import-method=auto) races with Docker's overlay filesystem during atomic renames. SettingNPM_CONFIG_PACKAGE_IMPORT_METHOD=copyvia env var in the Dockerfile tells pnpm to copy packages instead of hard-linking, avoiding the race condition. This only affects Docker builds — local dev continues using the.npmrcdefaults.Issue (if applicable)
Follow-up to #12099 — swap-widget deploy started failing after that merge
Risk
Low. Only changes Docker build behavior for
pnpm install. No runtime changes. Uses a well-documented pnpm configuration option.Testing
Engineering
pnpm installstep should complete without ENOENT errorsOperations
Screenshots (if applicable)
N/A
Summary by CodeRabbit