Render build fails on corepack enable; record the hosting ADR #240

Closed
opened 2026-10-04 21:13:59 +00:00 by root · 6 comments
root commented 2026-10-04 21:13:59 +00:00 (Migrated from gitlab.core-project.space)

Imported from GitHub amaurycoudr/chess-project#240, opened by @amaurycoudr on 2026-10-04 21:13 UTC.
Closed on GitHub on 2026-10-04 21:27 UTC as completed.


Problem Statement

PR #235 (spec #233) merged, and Render's production deploy of c4be632 failed twice, about 7 s into the build:

Internal Error: EROFS: read-only file system, unlink '/usr/bin/pnpm'
    at EnableCommand.generatePosixLink
==> Build failed

Render's native Node image ships its own pnpm in a read-only /usr/bin, and the blueprint's corepack enable tries to replace that symlink. Nothing is live.

Three smaller gaps came out of the same deploy:

  • Render gave the service a suffixed URL, https://chess-project-84ph.onrender.com. README.md, the wizard's DEFAULT_URL (scripts/setup-render.sh) and the comment in apps/front/src/room/api/client.ts ("There is no deployment yet…") still describe the unsuffixed or missing deployment.
  • The hosting decision, and the alternatives it beat, are recorded only in #233 and PR #235, not in an ADR.
  • ADR 0009's rationale says "The API ships no browser code", which stopped being true once the API served the front. The decision still holds.

Solution

One PR, which the owner asked for, including the ADR changes:

  • render.yaml: buildCommand: corepack pnpm install --frozen-lockfile && corepack pnpm build. This writes no symlink and still honours packageManager. Add env var COREPACK_ENABLE_DOWNLOAD_PROMPT: "0" so corepack never blocks on a download prompt.
  • Production URL: use https://chess-project-84ph.onrender.com in README.md, in scripts/setup-render.sh DEFAULT_URL (the STAGES part only; the library stays byte-identical to the wizard template), and in the client.ts comment.
  • ADR 0024 "Host on one free Render web service": the API serves the built front and /rpc from one origin, with a preview per PR.
    • Drivers: the in-memory RoomRegistry needs a single process, and the front calls same-origin /rpc.
    • Accepted cost: the instance sleeps after 15 min idle and takes ~1 min to wake. Rooms are wiped on sleep and on redeploy, which fits the 30-min Room TTL.
    • Rejected:
      • Fly.io: no free tier.
      • Koyeb and Zeabur: they sleep.
      • Netlify: its proxy cuts requests at 26 s and buffers SSE.
      • Vercel functions: streams die at 5 min, and it runs multiple instances.
      • Deno Deploy: multiple instances break the in-memory registry.
      • Cloudflare Durable Objects: a good long-term fit, but a 3–5 day rewrite.
    • Revisit with a Hetzner VM + Coolify (~€4/mo) if Render's sleep hurts.
    • Add a row to docs/adr/README.md.
  • ADR 0009: reword the "ships no browser code" rationale bullet so it stays true. The decision is unchanged.

Testing Decisions

  • No new behaviour in code. The gate is the five commands in CONTRIBUTING.md, plus bash -n and shellcheck on the wizard.
  • The real check happens after merge: Render redeploys main once CI is green, then the owner re-runs scripts/setup-render.sh for the stage-6 smoke test and the stage-7 preview check.
  • Still unverified: whether Turbo calls Render's /usr/bin/pnpm for per-package scripts (harmless), and whether startCommand's ${ORIGIN_ALLOWLIST:-$RENDER_EXTERNAL_URL} runs through a shell. Stage 6 proves the second.

Out of Scope

  • Changing the hosting platform.
> _Imported from GitHub [amaurycoudr/chess-project#240](https://github.com/amaurycoudr/chess-project/issues/240), opened by [@amaurycoudr](https://github.com/amaurycoudr) on 2026-10-04 21:13 UTC._ > _Closed on GitHub on 2026-10-04 21:27 UTC as completed._ <!-- github-issue:240 --> --- ## Problem Statement PR #235 (spec #233) merged, and Render's production deploy of `c4be632` failed twice, about 7 s into the build: ``` Internal Error: EROFS: read-only file system, unlink '/usr/bin/pnpm' at EnableCommand.generatePosixLink ==> Build failed ``` Render's native Node image ships its own pnpm in a read-only `/usr/bin`, and the blueprint's `corepack enable` tries to replace that symlink. Nothing is live. Three smaller gaps came out of the same deploy: - Render gave the service a suffixed URL, `https://chess-project-84ph.onrender.com`. `README.md`, the wizard's `DEFAULT_URL` (`scripts/setup-render.sh`) and the comment in `apps/front/src/room/api/client.ts` ("There is no deployment yet…") still describe the unsuffixed or missing deployment. - The hosting decision, and the alternatives it beat, are recorded only in #233 and PR #235, not in an ADR. - ADR 0009's rationale says "The API ships no browser code", which stopped being true once the API served the front. The decision still holds. ## Solution One PR, which the owner asked for, including the ADR changes: - **`render.yaml`:** `buildCommand: corepack pnpm install --frozen-lockfile && corepack pnpm build`. This writes no symlink and still honours `packageManager`. Add env var `COREPACK_ENABLE_DOWNLOAD_PROMPT: "0"` so corepack never blocks on a download prompt. - **Production URL:** use `https://chess-project-84ph.onrender.com` in `README.md`, in `scripts/setup-render.sh` `DEFAULT_URL` (the STAGES part only; the library stays byte-identical to the wizard template), and in the `client.ts` comment. - **ADR 0024 "Host on one free Render web service":** the API serves the built front and `/rpc` from one origin, with a preview per PR. - Drivers: the in-memory `RoomRegistry` needs a single process, and the front calls same-origin `/rpc`. - Accepted cost: the instance sleeps after 15 min idle and takes ~1 min to wake. Rooms are wiped on sleep and on redeploy, which fits the 30-min Room TTL. - Rejected: - Fly.io: no free tier. - Koyeb and Zeabur: they sleep. - Netlify: its proxy cuts requests at 26 s and buffers SSE. - Vercel functions: streams die at 5 min, and it runs multiple instances. - Deno Deploy: multiple instances break the in-memory registry. - Cloudflare Durable Objects: a good long-term fit, but a 3–5 day rewrite. - Revisit with a Hetzner VM + Coolify (~€4/mo) if Render's sleep hurts. - Add a row to `docs/adr/README.md`. - **ADR 0009:** reword the "ships no browser code" rationale bullet so it stays true. The decision is unchanged. ## Testing Decisions - No new behaviour in code. The gate is the five commands in `CONTRIBUTING.md`, plus `bash -n` and shellcheck on the wizard. - The real check happens after merge: Render redeploys `main` once CI is green, then the owner re-runs `scripts/setup-render.sh` for the stage-6 smoke test and the stage-7 preview check. - Still unverified: whether Turbo calls Render's `/usr/bin/pnpm` for per-package scripts (harmless), and whether `startCommand`'s `${ORIGIN_ALLOWLIST:-$RENDER_EXTERNAL_URL}` runs through a shell. Stage 6 proves the second. ## Out of Scope - Changing the hosting platform.
root (Migrated from gitlab.core-project.space) closed this issue 2026-10-04 21:27:30 +00:00
root commented 2026-10-13 10:22:14 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 074e3caa73

mentioned in commit 074e3caa73ee4aa5e8d2d84ac0db51800ecd86e7
root commented 2026-10-13 10:22:14 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 7927002a22

mentioned in commit 7927002a224f78c29816dd75aa992d915044c01e
root commented 2026-10-13 10:22:15 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit f0862e3b2b

mentioned in commit f0862e3b2b3770a0aa6f7565fa4343c85c6fb6dc
root commented 2026-10-13 10:22:15 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 3bb1ab6034

mentioned in commit 3bb1ab6034e45f10a19dda86cc4fc3e5d6179205
root commented 2026-10-13 10:22:15 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit b87944df82

mentioned in commit b87944df8248ef777667c2b5420ec9cf72a1b503
root commented 2026-10-13 10:22:16 +00:00 (Migrated from gitlab.core-project.space)

mentioned in commit 92d93b25a8

mentioned in commit 92d93b25a818cc3bb1647188aedd89224cc2e310
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
amaurycoudr/chess-project#240
No description provided.