2 months ago
Since 2026-08-17 every build in my monorepo fails at the cache-key stage:
Build Failed: build daemon returned an error < failed to solve:
failed to compute cache key: failed to calculate checksum of ref :
"/docs/marketing/package.json": not found >
The file is in the repo and is tracked in git. Nothing about it changed.
What I think is happening: railpack globs the git tree for package.json files and emits a COPY docs/marketing/package.json step. But my .dockerignore contains docs, so that path is not in the build context - and the COPY then fails. The build log shows railpack noticing the file:
↳ Found .dockerignore file, applying filters
↳ Found workspace with 3 packages
So the planner reads the git tree while the context obeys .dockerignore, and the two disagree.
Note that docs/marketing/ is not one of my workspaces - my root package.json declares only packages/*. It's a stray package.json for a one-off script that happens to live under docs/.
Why I think it's a regression:
- A build 2 weeks earlier on railpack-builder:mise-2026.7.15 succeeded, copying that same file.
- The same commit on railpack-builder:mise-2026.8.4 (railpack 0.36.4) fails.
- The file is byte-identical between the two.
Watch out for a misleading symptom. The dashboard surfaces this:
process "mise install" did not complete successfully:
exit code: 137: context canceled
137 reads like an OOM. It isn't. It's BuildKit cancelling sibling steps. Millisecond timestamps from the build log:
:28.3188 [err] copy docs/marketing/package.json <- actual first failure
:28.6857 [err] install mise packages: node <- +0.37s
:28.8167 [err] install apt packages: libatomic1 <- +0.13s
I lost time chasing builder memory because of this. The dashboard's own failure explanation also suggested the file "was deleted or moved" and that I should fix a path in railpack.toml / Dockerfile - I have neither file, and the file was present.
Workaround that works: untrack the offending package.json (and its lockfile) so the planner never sees it. Adding it to .gitignore is enough; the file can stay on disk.
Questions:
- Known regression between mise-2026.7.15 and mise-2026.8.4?
- Should the planner respect .dockerignore when globbing for manifests?
- Should it glob for package.json outside the workspace globs declared in the root package.json at all?
- Can a builder version be pinned per service as a stopgap?
Pinned Solution
2 months ago
Hi! Sorry about this, unfortunately not respecting the .dockerignore on initial load was a bug and it looks like your build relied on it. Updating your .dockerignore should fix the issue!
However, planning should respect the .dockerignore as well. I've added an issue to fix this!
4 Replies
2 months ago
This thread has been opened as a bounty so the community can help solve it.
Status changed to Open Railway • about 2 months ago
2 months ago
-
Likely yes. Railpack 0.36.0 changed when .dockerignore applies ; patterns now hit "when the local source is first loaded into BuildKit" (PR #373). Before, everything loaded and got filtered later, so the COPY still found the file. Now docs is gone before COPY runs. Fits your timeline. Haven't read the diff, so it's a lead not a confirmed cause.
-
My opinion: yes, or at least the two should agree. Planner reads the git tree, context obeys .dockerignore ; any COPY for an excluded path is guaranteed to fail. Harmless before 0.36, load-bearing now.
-
Docs say it shouldn't. Node workspace detection reads the workspaces field or pnpm-workspace.yaml, not a filesystem glob ; and your root declares only packages/*. So something else pulled that file in. Worth checking if your lockfile still references docs/marketing, or if it came from the install-step file copy. That's one bug vs two.
-
Don't think it's a knob. Each railpack binary bakes its builder tag in at compile time from the pinned mise version in core/mise/version.txt, so mise-2026.8.4 is a label for which railpack built it, not a separate axis. Pinning the builder means pinning railpack.
Instead of untracking , negation should work, railpack passes patterns to BuildKit and BuildKit handles !:
docs/**
!docs/marketing/package.json
Keeps it in git, keeps the rest of docs out.
2 months ago
Hi! Sorry about this, unfortunately not respecting the .dockerignore on initial load was a bug and it looks like your build relied on it. Updating your .dockerignore should fix the issue!
However, planning should respect the .dockerignore as well. I've added an issue to fix this!
officeoptibiz
1. Likely yes. Railpack 0.36.0 changed when .dockerignore applies ; patterns now hit "when the local source is first loaded into BuildKit" (PR #373). Before, everything loaded and got filtered later, so the COPY still found the file. Now docs is gone before COPY runs. Fits your timeline. Haven't read the diff, so it's a lead not a confirmed cause. 2. My opinion: yes, or at least the two should agree. Planner reads the git tree, context obeys .dockerignore ; any COPY for an excluded path is guaranteed to fail. Harmless before 0.36, load-bearing now. 3. Docs say it shouldn't. Node workspace detection reads the workspaces field or pnpm-workspace.yaml, not a filesystem glob ; and your root declares only packages/*. So something else pulled that file in. Worth checking if your lockfile still references docs/marketing, or if it came from the install-step file copy. That's one bug vs two. 4. Don't think it's a knob. Each railpack binary bakes its builder tag in at compile time from the pinned mise version in core/mise/version.txt, so mise-2026.8.4 is a label for which railpack built it, not a separate axis. Pinning the builder means pinning railpack. Instead of untracking , negation should work, railpack passes patterns to BuildKit and BuildKit handles !: docs/** !docs/marketing/package.json Keeps it in git, keeps the rest of docs out.
2 months ago
Confirmed on our side — and I could settle your point 3 with evidence. It's one bug, not two.
Root package.json declares only packages/*, and root package-lock.json has zero references to that path. So workspace detection and the lockfile are both clean. It's the install-step copy you suspected: SupportingInstallFiles() globs repo-wide, separate from workspace resolution, and picks up a non-workspace package.json. After #373 the context has already dropped that dir, so the COPY can't checksum it.
Your point 4 is a useful correction — the builder tag being baked in from core/mise/version.txt means the mise version was a red herring in my original report.
On the negation suggestion: worth noting the glob also matches lockfiles. Two of our builds failed on different files — one on package.json, one on package-lock.json — so it needs both negated, not just the first. Our current rule is also bare docs rather than docs/**, and the two forms resolve negation differently.
We went with untracking the two manifests instead, which is verified green in production. Negation is the better option for anyone who needs them version-controlled.
mikebianco
Hi! Sorry about this, unfortunately *not* respecting the `.dockerignore` on initial load was a bug and it looks like your build relied on it. Updating your `.dockerignore` should fix the issue! However, planning should respect the `.dockerignore` as well. I've added an [issue to fix this](https://github.com/railwayapp/railpack/issues/707)!
2 months ago
Thanks — that reframes it usefully. I'd been treating #373 as a regression; if the prior behaviour was the bug then there's nothing to wait out, and pinning below 0.36.0 is actively the wrong move since it just re-enables it. Good to know #707 covers the planner side.
For anyone finding this later: we fixed it by untracking the two non-workspace manifests, which turns out to be aligned with the corrected behaviour rather than a workaround. If you need them tracked, .dockerignore negation works — but note the install-file glob matches lockfiles too, so negate both package.json and package-lock.json, not just the first.
Status changed to Solved mayori • about 2 months ago