Skip to content

fix: stop Next.js 16.3 from endlessly retrying page prefetches - #1348

Open
ahmadaccino wants to merge 1 commit into
opennextjs:mainfrom
ahmadaccino:fix/next-16-prefetch-loop
Open

fix: stop Next.js 16.3 from endlessly retrying page prefetches#1348
ahmadaccino wants to merge 1 commit into
opennextjs:mainfrom
ahmadaccino:fix/next-16-prefetch-loop

Conversation

@ahmadaccino

@ahmadaccino ahmadaccino commented Aug 19, 2026

Copy link
Copy Markdown

Summary

Fixes #1334.

  • serve cached App Router segment payloads even when Next.js prefetch inlining is enabled
  • apply a focused, fail-fast patch to the generated OpenNext middleware only when cache interception is enabled
  • update playground16 to Next.js 16.3.1 and add unit and Worker regression coverage plus a patch changeset

Root cause

@opennextjs/aws@4.1.0 only selected segmentData when experimental.prefetchInlining was falsy. Next.js 16.3 enables that setting by default and normalizes it to an object, so cache interception answered Next-Router-Segment-Prefetch requests with the full-page RSC payload instead of the requested segment.

Next.js still requests the /_tree response and any outlined segment bundles when inlining is enabled. Because the client never received the segment response or its x-nextjs-postponed: 2 header, it kept requesting the route tree indefinitely. The reproduction generated 3,482 repeated /_tree requests in five seconds.

The patch removes only the incorrect prefetch-inlining gate and keeps the existing segmentData membership check. It is scoped to cache-interception builds and fails loudly if the pinned upstream implementation changes. The corresponding upstream report is opennextjs/opennextjs-aws#1212.

Validation

  • pnpm code:checks
  • pnpm test (35 test files, 345 tests)
  • SKIP_NEXT_APP_BUILD=true pnpm --filter playground16 exec playwright test e2e/prefetch.cloudflare.spec.ts -c e2e/playwright.config.ts (1 passed)
  • pnpm --filter playground16 exec playwright test e2e/prefetch.cloudflare.spec.ts -c e2e/playwright.turbopack.config.ts (1 passed)

Open in Devin Review

@changeset-bot

changeset-bot Bot commented Aug 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: de72c13

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@opennextjs/cloudflare Patch

Not sure what this means? Click here to learn what changesets are.

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

@ahmadaccino ahmadaccino changed the title fix: stop endless RSC prefetch requests in Next.js 16.3 fix: stop Next.js 16.3 from endlessly retrying page prefetches Aug 19, 2026

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@spira-unplugged

Copy link
Copy Markdown

Confirming this against production and against an older adapter line. Two notes that may help scoping, plus a request.

I hit this on a live site: deploying next 16.2.6 -> 16.3.1 took a small app from 30-40k Workers requests/day to 329M and 175M on two consecutive days, with R2 Class B reads tracking it roughly 1:1 (details in #1334). Your root-cause description matches what I observed, so thank you for chasing it down.

The ast-grep rule matches @opennextjs/aws@3.10.2 verbatim, so this is not 4.1.0-only

The doc comment on patchCacheInterceptor says "OpenNext AWS 4.1.0 treats prefetch inlining as if it eliminates segment responses". @opennextjs/cloudflare@1.19.2 pins @opennextjs/aws@3.10.2, and getBodyForAppRouter there emits the same expression:

// node_modules/@opennextjs/aws/dist/core/routing/cacheInterceptor.js
const isSegmentResponse = Boolean(segmentHeader) &&
    segmentHeader in (cachedValue.segmentData || {}) &&
    !NextConfig.experimental?.prefetchInlining;

That is structurally identical to segmentPrefetchRule's pattern, so patchCacheInterceptorSource should rewrite it cleanly on 1.19.x as well as 1.20.x. Worth reflecting in the doc comment and the changeset - as written, someone on 1.19.x reading this may conclude they are unaffected, and they are not.

patchCacheInterceptorSource throws when nothing matches

Fail-fast is a reasonable default here, but it turns "pattern absent" into a hard build failure for every cache-interception user, including anyone on an aws version that renames or reshapes the expression without being buggy. Would it be worth throwing only when the known-bad !NextConfig.experimental?.prefetchInlining substring is present in a shape the rule cannot rewrite, and warning otherwise? Either behaviour is defensible - raising it because the failure would land on people who are not otherwise affected.

Ask

Is there a maintainer who could review this? As far as I can see there is no PR against @opennextjs/aws for opennextjs/opennextjs-aws#1212 yet, so this patch is currently the only route to a fix for anyone running cache interception on Next 16.3. #1334 and #1327 have no maintainer response either, and the failure mode is unbounded client-side retries against a metered runtime.

Happy to run a canary build on a preview deployment of the app that hit this and report the numbers back.

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.

Next 16.3.0 + OpenNext triggers an unbounded RSC prefetch loop

2 participants