◐ Off-By-One · answer catalog

nextjs-dev-bind-mounted-next-cache-chunk-corruption

2 answer(s)typescriptdockertypescriptdocker

nextjs-dev-bind-mounted-next-cache-chunk-corruption

📦 Source in repository (JSON)

Answer 1

The solution is written to ~/nextjs-next-cache-fix.md. Here's the condensed version.

Root cause

The compose bind mount ./apps/web:/app/apps/web also shared the host's apps/web/.next build cache with the container. .next/server/webpack-runtime.js maps numeric chunk IDs to physical files (./5799.js, ./8215.js). A host-side build (or second process) rewrote/pruned .next and regenerated the manifest, while the running next dev process kept referencing chunk files that had been deleted. Result: MODULE_NOT_FOUND → /login HTTP 500 → unhealthy container. .next is disposable per-runtime build state and must never be shared between host and container.

Fix (docker-compose.yml)

Keep the source bind mount but shadow the nested .next with a container-only volume (mount order matters — bind first, volume second):

services:
  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile
      target: dev
    working_dir: /app/apps/web
    command: pnpm --filter web dev
    volumes:
      - ./apps/web:/app/apps/web
      - web_next:/app/apps/web/.next          # critical: isolate cache
      - web_node_modules:/app/apps/web/node_modules
    ports:
      - "3000:3000"

volumes:
  web_next:
  web_node_modules:

Also add .next to .dockerignore/.gitignore.

Apply

docker compose stop web
docker compose rm -sf web
docker volume rm "$(docker volume ls -q | grep -E 'web_next$')" || true
docker compose up -d --force-recreate web

Verify

docker compose ps                                              # Up (healthy)
curl -fsS -o /dev/null -w 'HTTP %{http_code}\n' localhost:3000/login   # HTTP 200
curl -fsS localhost:3000/login | grep -Ei 'type="(email|password)"|sign in'  # controls render
docker compose logs --since=2m web | grep -Ei 'MODULE_NOT_FOUND|5799|8215'   # clean

Confirm isolation — .next must be a volume, source a bind:

docker inspect "$(docker compose ps -q web)" \
  --format '{{range .Mounts}}{{.Type}}\t{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'

The full document includes the detailed analysis, anonymous-volume alternative, all verification steps, and prevention guidance.

Evidence & signatures

# Evidence
- Problem class: nextjs-dev-bind-mounted-next-cache-chunk-corruption
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-12T21:31:06.552Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A Docker Compose Next.js dev service bind-mounted the entire host apps/web directory, including .next. Host-side builds and long-running container dev output shared that cache. The live container became unhealthy and /login returned HTTP 500 with MODULE_NOT_FOUND for numbered .next server chunks. Isolate /app/apps/web/.next with a container-only volume, recreate the web service, and verify rendered login controls plus healthy status.", "environment": "Linux rootless Docker Compose; host repo bind-mounted into container", "language": "typescript", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "nextjs-dev-bind-mounted-next-cache-chunk-corruption", "provider": "openrouter", "solved_at": "2026-09-12T21:31:06.552Z", "version": "Next.js 15.5.25"}

Answer 2

The solution is written to ~/nextjs-next-cache-fix.md. Here's the condensed version.

Root cause

The compose bind mount ./apps/web:/app/apps/web also shared the host's apps/web/.next build cache with the container. .next/server/webpack-runtime.js maps numeric chunk IDs to physical files (./5799.js, ./8215.js). A host-side build (or second process) rewrote/pruned .next and regenerated the manifest, while the running next dev process kept referencing chunk files that had been deleted. Result: MODULE_NOT_FOUND → /login HTTP 500 → unhealthy container. .next is disposable per-runtime build state and must never be shared between host and container.

Fix (docker-compose.yml)

Keep the source bind mount but shadow the nested .next with a container-only volume (mount order matters — bind first, volume second):

services:
  web:
    build:
      context: .
      dockerfile: apps/web/Dockerfile
      target: dev
    working_dir: /app/apps/web
    command: pnpm --filter web dev
    volumes:
      - ./apps/web:/app/apps/web
      - web_next:/app/apps/web/.next          # critical: isolate cache
      - web_node_modules:/app/apps/web/node_modules
    ports:
      - "3000:3000"

volumes:
  web_next:
  web_node_modules:

Also add .next to .dockerignore/.gitignore.

Apply

docker compose stop web
docker compose rm -sf web
docker volume rm "$(docker volume ls -q | grep -E 'web_next$')" || true
docker compose up -d --force-recreate web

Verify

docker compose ps                                              # Up (healthy)
curl -fsS -o /dev/null -w 'HTTP %{http_code}\n' localhost:3000/login   # HTTP 200
curl -fsS localhost:3000/login | grep -Ei 'type="(email|password)"|sign in'  # controls render
docker compose logs --since=2m web | grep -Ei 'MODULE_NOT_FOUND|5799|8215'   # clean

Confirm isolation — .next must be a volume, source a bind:

docker inspect "$(docker compose ps -q web)" \
  --format '{{range .Mounts}}{{.Type}}\t{{.Source}} -> {{.Destination}}{{"\n"}}{{end}}'

The full document includes the detailed analysis, anonymous-volume alternative, all verification steps, and prevention guidance.

Evidence & signatures

# Evidence
- Problem class: nextjs-dev-bind-mounted-next-cache-chunk-corruption
- Model: openrouter/deepseek/deepseek-v4.1-flash
- Solved: 2026-09-12T21:31:06.552Z
- Verification: solution produced by pi in sandbox; see signatures.json
{"description": "A Docker Compose Next.js dev service bind-mounted the entire host apps/web directory, including .next. Host-side builds and long-running container dev output shared that cache. The live container became unhealthy and /login returned HTTP 500 with MODULE_NOT_FOUND for numbered .next server chunks. Isolate /app/apps/web/.next with a container-only volume, recreate the web service, and verify rendered login controls plus healthy status.", "environment": "Linux rootless Docker Compose; host repo bind-mounted into container", "language": "typescript", "model": "openrouter/deepseek/deepseek-v4.1-flash", "problem_class": "nextjs-dev-bind-mounted-next-cache-chunk-corruption", "provider": "openrouter", "solved_at": "2026-09-12T21:31:06.552Z", "version": "Next.js 15.5.25"}
Generated from the verified corpus · MIT licensedBack to the catalog