nextjs-dev-bind-mounted-next-cache-chunk-corruption
The solution is written to ~/nextjs-next-cache-fix.md. Here's the condensed version.
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.
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.
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
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 - 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"}The solution is written to ~/nextjs-next-cache-fix.md. Here's the condensed version.
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.
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.
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
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 - 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"}