Skip to content

SMOODEV-4146: Keep APP_PAGE segmentData a Map in the S3 cache - #14

Merged
brentrager merged 1 commit into
mainfrom
SMOODEV-4146-segment-data
Oct 24, 2026
Merged

brentrager merged 1 commit into
mainfrom
SMOODEV-4146-segment-data

Conversation

@brentrager

Copy link
Copy Markdown
Contributor

Problem

Next 16 keeps an APP_PAGE's per-segment prefetch payloads in segmentData: Map<string, Buffer>. JSON.stringify has no form for a Map, so the S3 cache handler stored it as {}. On a cache hit Next calls cachedData.segmentData.get(segmentPrefetchHeader) (next/dist/build/templates/app-page.js), which throws — every client segment prefetch (Next-Router-Segment-Prefetch: /_tree) of an ISR/SSG page answers 500 with an empty body.

On smoo.ai that's /, /help, /data-deletion, /privacy-policy, prefetched from links across the dashboard. Found by the e2e route sweep (SMOODEV-4130); reproducible without auth:

curl -H 'RSC: 1' -H 'Next-Router-Prefetch: 1' -H 'Next-Router-Segment-Prefetch: /_tree' 'https://smoo.ai/help?_rsc=x'  # 500, x-nextjs-cache: HIT

Solution

  • serialize encodes Maps as { __map: [[k, v], …] } (the replacer recurses into the entries, so their Buffers are base64'd as before); deserialize rebuilds the Map.
  • An entry written before this fix (segment payloads already lost as {}) reads as a miss, so Next regenerates it rather than serving a broken entry — no S3 purge needed.
  • Release 0.2.3.

Verification

  • Two new tests (Map round-trip of Buffers; legacy {} entry → miss) failed before the fix, pass after; existing Buffer tests still pass (node --test src/next/cache-handler.test.cjs: 4/4).
  • Shape matches Next 16.2.6's own file-system cache (segmentData = new Map() of segmentPath → Buffer).

Jira: https://smooai.atlassian.net/browse/SMOODEV-4146

🤖 Generated with Claude Code

https://claude.ai/code/session_01LbevoiGNpgJy6qTPvk4EVt

Next 16 stores an APP_PAGE's per-segment prefetch payloads in a Map, and
JSON.stringify has no form for a Map — it was stored as {}. On a cache hit
Next calls cachedData.segmentData.get(...), which threw, so every client
segment prefetch (Next-Router-Segment-Prefetch) of an ISR/SSG page answered
500: smoo.ai's /, /help, /data-deletion and /privacy-policy, prefetched from
links all over the dashboard.

Maps now travel as { __map: entries } (their Buffers encoded as before), and an
entry written before this fix — segment payloads already lost — reads as a miss
so Next regenerates it instead of serving it. Release 0.2.3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LbevoiGNpgJy6qTPvk4EVt
@changeset-bot

changeset-bot Bot commented Oct 24, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c64c04a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@brentrager
brentrager merged commit f4ad75b into main Oct 24, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant