error persists across Nixpacks and Dockerfile builds
dontaybee-cyber
FREEOP

6 months ago

BuildKit cache mount corrupted at /app/node_modules/@types/node — error persists across Nixpacks and Dockerfile builds, across multiple deploys. Error: cannot copy to non-directory: /var/lib/buildkit/runc-overlayfs/cachemounts/buildkitXXXXXXXXXX/app/node_modules/@types/node

$10 Bounty

1 Replies

Status changed to Awaiting Railway Response Railway 6 months ago


ayalaa12
FREETop 5% Contributor

a month ago

That path identifies a cache-mount type collision, not an application compile error: the persisted mount already has node_modules/@types/node as a non-directory entry (often a stale symlink or partial install), while the next dependency layer needs to create/copy a directory there. Repeating deploys reattaches the same corrupt mount, which explains why changing from Nixpacks to a Dockerfile did not clear it.

Use one no-cache build as the discriminator:

  1. Set the service variable NO_CACHE=1, apply the staged change, then run Deploy Latest Commit (or railway up). Do not use Restart; it reuses the built image. Railway's current build configuration documents NO_CACHE=1 as the switch that disables build-layer reuse, and Deploy Latest Commit performs a full rebuild.

  2. Ensure neither the repository nor upload context contains dependencies:

    
    git ls-files node_modules
    
    git ls-files -s | grep 'node_modules/@types/node'
    

    Both should be empty. Add node_modules to .gitignore and .dockerignore; remove any committed file/symlink under that path. Do not print environment files or registry tokens.

  3. Do not cache /app/node_modules. Cache the package manager's download store and recreate node_modules deterministically from the lockfile. For npm, the dependency stage should follow this shape:

    
    # syntax=docker/dockerfile:1
    
    FROM node:20-bookworm-slim AS build
    
    WORKDIR /app
    
    COPY package.json package-lock.json ./
    
    RUN --mount=type=cache,id=s/<service-id>-/root/.npm,target=/root/.npm \
    
        npm ci --cache /root/.npm
    
    COPY . .
    
    RUN npm run build
    

    Replace <service-id> with the actual Railway service ID as required by Railway's cache-mount format. If the final image needs production dependencies, create them in a clean final stage with npm ci --omit=dev; do not overlay a cached node_modules directory or copy host dependencies into it.

  4. Keep exactly one lockfile for the selected package manager and use its clean-install command (npm ci, pnpm install --frozen-lockfile, or the equivalent). Mixing npm/yarn/pnpm layouts can recreate the file-versus-directory collision even after the server cache is bypassed.

Interpret the result:

  • If the no-cache build succeeds, the old cache mount was the fault. Keep the new package-store cache target, remove NO_CACHE=1, and run one more build to prove the clean cache is reusable.
  • If the same path fails with NO_CACHE=1, the collision is in the source/build stages rather than Railway's stored cache. Inspect the line immediately before the error for a COPY into /app/node_modules, a committed dependency/symlink, or a second package-manager install; removing that overlay is the fix.
  • If a no-cache build still references the old cache-mount ID even after the Dockerfile no longer mounts /app/node_modules, send Railway the deployment ID, service ID, builder type and the failing cache-mount path so staff can delete that exact orphaned mount. Do not recreate the service or delete a healthy deployment first.

Official references:


Welcome!

Sign in to your Railway account to join the conversation.

Loading...