fix(web): restore /flows and /docs on Next 16.3.8 (fix forward, alternative to #129)

Merged
KH
4d ago
+75-1

Production incident

/flows and every /docs/<slug> page have returned 500 since #126 (Next.js 16.3.5 → 16.3.8) deployed at 2026-10-02 04:40 UTC.

This is the fix-forward: it keeps Next 16.3.8. #129 is the alternative that pins back to 16.3.5. Merge one and close the other.

Cause

  • Next 16.3.8 looks prerendered pages up under a new route-scoped key: /route-cache/<KIND>/<sha256 of source route>/$<page path> (next/dist/server/lib/route-cache-key.js).
  • The OpenNext static-assets incremental cache stores them as <build id>/<page path>.cache and passes the key through unchanged, so every lookup misses.
  • On a miss the Worker renders the page at request time. Two kinds of page cannot render in the Workers runtime:
    • docs MDX: EvalError: Code generation from strings disallowed for this context
    • /flows: CompileError: WebAssembly.instantiate(): Wasm code generation disallowed by embedder
  • Other pages (/, /blog) return 200 only because they survive a live render; they are also missing the cache.

Change

  • web/lib/prerender-cache-key.ts: translates a route-scoped key back to its page path; any other key passes through.
  • web/open-next.config.ts: wraps the static-assets cache with that translation. The cache name is unchanged, so populateCache still copies the prerenders into assets.
  • web/lib/test/prerender-cache-key.test.ts: builds keys with Next's own getRouteCacheKey, so another change to the key shape fails CI.

Verification (local opennextjs-cloudflare build + populateCache local + wrangler dev, Next 16.3.8)

PathWithout this changeWith this change
/200, cache MISS200, cache HIT
/flows500200, cache HIT
/docs/introduction500200, cache HIT
/flows/plugins200, cache MISS200, cache HIT
/blog200, cache MISS200, cache HIT

With the change, /docs/quickstart, /docs/agents/cli, /docs/7.1.1/quickstart, /about and /docs/introduction.md also return 200 from the cache.

  • Web tests: 328 passed. tsc --noEmit: clean.
  • Not verified on the deployed runtime yet: check /flows and /docs/introduction on this PR's preview URL before merging.

Risk compared with #129

This depends on an internal Next key format and should be removed once @opennextjs/cloudflare handles route-scoped keys itself. #129 returns to the exact dependency set that was healthy in production yesterday.

@khaliqgant — needs the two reviews plus a human merge to deploy.

šŸ¤– Generated with Claude Code


[!NOTE]
Cursor Bugbot is generating a summary for commit 5bf3e62aa29b4960c837c262c414dd8601bb8f45. Configure here.


Summary by cubic

Fixes the production 500s on /flows and every /docs/<slug> page that started with the Next.js 16.3.8 upgrade in #126.

Changes

  • Wraps the OpenNext static-assets incremental cache to translate Next 16.3.8's route-scoped keys back to the page paths the cache stores them under.
  • Tests build keys with Next's own key builder, so a future key-shape change fails CI instead of production.

Risk

  • Relies on an internal Next key format; remove once @opennextjs/cloudflare handles route-scoped keys itself.
  • Alternative #129 pins Next back to 16.3.5; merge one and close the other.

Agent Relay sessions

  • claude session fe983435 Ā· opened via gh pr create Ā· last active 2026-10-02