Skip to content

A bake corrupts the dev server's .next, and #230's self-heal is blind to it (200 + dead chunk ≠ 5xx) #298

Description

@TortoiseWolfe

A bake corrupts the dev server's .next, and #230's self-heal cannot see it

Hit three times in one session (2026-07-16), each time costing a diagnosis from scratch. The third time it looked exactly like a code bug and sent me hunting a dependency override that was innocent.

Symptom

Every route serves HTTP 200. The page renders its static shell — nav, footer — and nothing else. The console shows:

TypeError: Cannot read properties of undefined (reading 'call')
    at options.factory (.../_next/static/chunks/webpack.js:704:31)
    at __webpack_require__ (.../webpack.js:29:33)

Webpack's __webpack_require__ found an undefined module factory — a stale chunk graph, not a code error.

Trigger

Bulk file writes under the running dev server. docker/docker-entrypoint.sh's own comment already names it:

"Bulk file changes under the running dev server (bakes, branch switches) racing the HMR compiler on the WSL2 bind mount corrupt .next"

A pnpm bake rewrites six public/twins/chatt/* artifacts. A multi-file edit does it too.

Why the watchdog is blind

#230's supervisor triggers on sustained HTTP 5xx. This failure serves 200 and dies in the browser. Confirmed while every route's client JS was dead:

/chatt/  -> HTTP 200
[self-heal] lines in the last 15m: 0

So the supervisor never fires and the page stays broken indefinitely, with no recovery and no signal.

#293 fixed builds clobbering .next (production builds now run in their own container). Bakes still do it, and this shape of the failure is invisible to the watchdog.

Remedy today

docker compose restart scripthammer — reliably fixes it. The cost is that you have to know that, and the symptom impersonates a code bug convincingly.

Options (the issue should decide — not obvious)

  1. Widen the self-heal probe beyond status codes. scripts/check-chunks-parse.mjs already exists and is exactly this check — fetch a known chunk, parse it, recycle .next if it fails. Tempting because the tool is already written, but it makes the healthcheck heavier and runs on every interval.
  2. Have the bake recycle .next when it finishes. Narrower, cheaper, and targets the known trigger — but only that trigger; a multi-file edit still corrupts silently.
  3. Just document it in CLAUDE.md ("restart after a bake"). Cheapest; relies on humans remembering, which is what failed three times today.

Why it matters beyond dev comfort

This is the same class as #294 (webpack emits something the browser can't use, while every gate stays green) and #288 (all suites green, product unusable). The signal says fine; the product is dead. That pattern has now cost this repo three separate outages-of-a-kind.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions