nextjs - ✅(Solved) Fix Prefetch full refetch the payload if there is already an inflight on Next 16 [1 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
vercel/next.js#86400Fetched 2026-04-08 02:11:10
View on GitHub
Comments
0
Participants
1
Timeline
4
Reactions
2
Participants
Timeline (top)
cross-referenced ×1issue_type_added ×1labeled ×1referenced ×1

Fix Action

Fixed

PR fix notes

PR #86700: fix: prevent duplicate RSC requests when navigation happens during inflight prefetch

Description (problem / solution / changelog)

What?

Fixed duplicate RSC requests when navigation happens while a prefetch is already in progress. Previously, when a user clicked a link quickly after prefetch started, navigation would immediately make a new RSC request instead of waiting for the inflight prefetch to complete.

Why?

When a prefetch has Pending status (request already in flight), the navigation logic was only checking for Fulfilled status. If the prefetch was still pending, navigation would fall through to navigateDynamicallyWithNoPrefetch, which immediately makes a new RSC request. This caused duplicate requests and wasted network bandwidth, especially when users clicked links quickly after prefetch was initiated.

How?

  • Added promise field to PendingRouteCacheEntry to track navigation requests waiting for prefetch completion
  • Created waitForRouteCacheEntry function (similar to waitForSegmentCacheEntry) that returns a promise resolving when the prefetch completes
  • Updated fulfillRouteCacheEntry and rejectRouteCacheEntry to resolve the promise when prefetch completes or fails
  • Modified navigate function to check for Pending status and wait for prefetch completion before making a new request
  • Added e2e test to verify only one request is made when navigation happens during inflight prefetch

The implementation follows the same pattern already used for segment cache entries, ensuring consistency across the codebase.

Fixes #86400

Changed files

  • .gitignore (modified, +1/-0)
  • crates/next-core/src/next_shared/webpack_rules/sass.rs (modified, +34/-2)
  • packages/next/src/build/create-compiler-aliases.ts (modified, +7/-2)
  • packages/next/src/build/entries.ts (modified, +0/-6)
  • packages/next/src/client/components/app-router-announcer.tsx (modified, +40/-15)
  • packages/next/src/client/components/router-reducer/reducers/navigate-reducer.ts (modified, +6/-1)
  • packages/next/src/client/components/segment-cache/cache.ts (modified, +41/-0)
  • packages/next/src/client/components/segment-cache/navigation.ts (modified, +97/-0)
  • packages/next/src/client/web-vitals.ts (modified, +104/-7)
  • packages/next/src/server/app-render/create-component-styles-and-scripts.tsx (modified, +1/-1)
  • packages/next/src/server/app-render/dynamic-rendering.ts (modified, +9/-0)
  • packages/next/src/server/app-render/get-layer-assets.tsx (modified, +1/-1)
  • packages/next/src/server/base-server.ts (modified, +16/-0)
  • packages/next/src/server/config.ts (modified, +3/-1)
  • packages/next/src/server/lib/router-server.ts (modified, +23/-0)
  • packages/next/src/server/next-server.ts (modified, +45/-7)
  • packages/next/src/server/route-modules/app-route/module.ts (modified, +91/-0)
  • packages/next/src/server/route-modules/app-route/shared-modules.ts (modified, +19/-1)
  • packages/next/src/server/route-modules/route-module.ts (modified, +1/-1)
  • test/e2e/app-dir/app-middleware-proxy-esm/app-middleware-proxy-esm.test.ts (added, +28/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/api/test/route.js (added, +5/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/layout.js (added, +7/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/page.js (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/app/rewritten/page.js (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/next.config.js (added, +6/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/package.json (added, +3/-0)
  • test/e2e/app-dir/app-middleware-proxy-esm/proxy.js (added, +24/-0)
  • test/e2e/app-dir/app-routes/app-custom-routes.test.ts (modified, +14/-0)
  • test/e2e/app-dir/app-routes/app/layout.tsx (modified, +2/-0)
  • test/e2e/app-dir/app-routes/app/test-layout-cookies/layout.tsx (added, +20/-0)
  • test/e2e/app-dir/app-routes/app/test-layout-cookies/page.tsx (added, +5/-0)
  • test/e2e/app-dir/app/useReportWebVitals.test.ts (modified, +52/-0)
  • test/e2e/app-dir/cache-components-errors/cache-components-dynamic-metadata-empty-shell.test.ts (added, +157/-0)
  • test/e2e/app-dir/cache-components-errors/fixtures/dynamic-metadata-empty-shell/app/dynamic-metadata-connection-empty-shell/page.tsx (added, +18/-0)
  • test/e2e/app-dir/cache-components-errors/fixtures/dynamic-metadata-empty-shell/app/layout.tsx (added, +11/-0)
  • test/e2e/app-dir/cache-components-errors/fixtures/dynamic-metadata-empty-shell/next.config.js (added, +9/-0)
  • test/e2e/app-dir/cache-components/cache-components.test.ts (modified, +24/-0)
  • test/e2e/app-dir/interception-search-params-update/app/@modal/(.)search/page.tsx (added, +13/-0)
  • test/e2e/app-dir/interception-search-params-update/app/@modal/default.tsx (added, +3/-0)
  • test/e2e/app-dir/interception-search-params-update/app/@modal/layout.tsx (added, +9/-0)
  • test/e2e/app-dir/interception-search-params-update/app/layout.tsx (added, +13/-0)
  • test/e2e/app-dir/interception-search-params-update/app/page.tsx (added, +11/-0)
  • test/e2e/app-dir/interception-search-params-update/app/search/page.tsx (added, +55/-0)
  • test/e2e/app-dir/interception-search-params-update/interception-search-params-update.test.ts (added, +77/-0)
  • test/e2e/app-dir/interception-search-params-update/next.config.js (added, +6/-0)
  • test/e2e/app-dir/segment-cache/prefetch-inflight-duplicate/app/layout.tsx (added, +11/-0)
  • test/e2e/app-dir/segment-cache/prefetch-inflight-duplicate/app/page.tsx (added, +12/-0)
  • test/e2e/app-dir/segment-cache/prefetch-inflight-duplicate/app/search/page.tsx (added, +8/-0)
  • test/e2e/app-dir/segment-cache/prefetch-inflight-duplicate/next.config.js (added, +5/-0)
  • test/e2e/app-dir/segment-cache/prefetch-inflight-duplicate/prefetch-inflight-duplicate.test.ts (added, +112/-0)
  • test/integration/next-image-new/loader-config-windows/dummy-loader.js (added, +3/-0)
  • test/integration/next-image-new/loader-config-windows/next.config.js (added, +8/-0)
  • test/integration/next-image-new/loader-config-windows/pages/get-img-props.js (added, +34/-0)
  • test/integration/next-image-new/loader-config-windows/pages/index.js (added, +35/-0)
  • test/integration/next-image-new/loader-config-windows/public/logo.png (added, +0/-0)
  • test/integration/next-image-new/loader-config-windows/test/index.test.ts (added, +89/-0)
  • test/production/app-dir/turbopack-bootstrap-scss-windows/app/globals.scss (added, +15/-0)
  • test/production/app-dir/turbopack-bootstrap-scss-windows/app/layout.tsx (added, +18/-0)
  • test/production/app-dir/turbopack-bootstrap-scss-windows/app/page.tsx (added, +12/-0)
  • test/production/app-dir/turbopack-bootstrap-scss-windows/index.test.ts (added, +43/-0)
  • test/production/app-dir/turbopack-bootstrap-scss-windows/next.config.js (added, +6/-0)
  • test/production/app-dir/turbopack-route-handler-notfound/app/api/not-found/route.ts (added, +5/-0)
  • test/production/app-dir/turbopack-route-handler-notfound/app/layout.tsx (added, +13/-0)
  • test/production/app-dir/turbopack-route-handler-notfound/app/page.tsx (added, +5/-0)
  • test/production/app-dir/turbopack-route-handler-notfound/index.test.ts (added, +33/-0)
  • test/unit/app-router-announcer.test.tsx (added, +319/-0)
  • test/unit/router-server-process-listeners.test.ts (added, +93/-0)
  • turbopack/crates/turbopack-ecmascript/src/minify.rs (modified, +6/-6)
  • turbopack/crates/turbopack-node/js/src/transforms/webpack-loaders.ts (modified, +7/-1)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/input/index.js (added, +25/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/options.json (added, +9/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/[turbopack]_runtime.js (added, +4/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/[turbopack]_runtime.js.map (added, +5/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/bf321_tests_snapshot_basic_ecmascript_minify_inline_conflict_input_index_3a45d1a2.js (added, +3/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/bf321_tests_snapshot_basic_ecmascript_minify_inline_conflict_input_index_3a45d1a2.js.map (added, +1/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/index.entry.js (added, +4/-0)
  • turbopack/crates/turbopack-tests/tests/snapshot/basic/ecmascript_minify_inline_conflict/output/index.entry.js.map (added, +5/-0)

Code Example

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:15 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 14
Binaries:
  Node: 22.20.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 16.0.3 // Latest available version is detected (16.0.3).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/hamidrezahanafi/prefetch-full

To Reproduce

  1. npm install
  2. npm run build
  3. npm run start
  4. try to click on search link as fast as possible

Current vs. Expected behavior

Current Extra RSC request is being made even though a full prefetch is still on flight Expected Only one RSC request should go out even if the click is super fast

Provide environment information

Operating System:
  Platform: darwin
  Arch: arm64
  Version: Darwin Kernel Version 24.6.0: Wed Oct 15 21:12:15 PDT 2025; root:xnu-11417.140.69.703.14~1/RELEASE_ARM64_T6041
  Available memory (MB): 49152
  Available CPU cores: 14
Binaries:
  Node: 22.20.0
  npm: 10.9.3
  Yarn: 1.22.22
  pnpm: N/A
Relevant Packages:
  next: 16.0.3 // Latest available version is detected (16.0.3).
  eslint-config-next: N/A
  react: 19.2.0
  react-dom: 19.2.0
  typescript: 5.9.3
Next.js Config:

Which area(s) are affected? (Select all that apply)

Route Handlers

Which stage(s) are affected? (Select all that apply)

next start (local)

Additional context

No response

extent analysis

TL;DR

  • Implement a debouncing mechanism to prevent multiple RSC requests when clicking the search link rapidly.

Guidance

  • Review the prefetch implementation in the provided code to identify potential issues with concurrent requests.
  • Consider adding a flag to track whether a full prefetch is currently in flight and skip subsequent RSC requests until it completes.
  • Investigate using a library like lodash.debounce to simplify the debouncing logic.
  • Verify the fix by repeating the steps to reproduce the issue and checking the network requests.

Example

import debounce from 'lodash.debounce';

const isPrefetching = false;
const debouncedPrefetch = debounce(async () => {
  if (isPrefetching) return;
  isPrefetching = true;
  try {
    // Perform the prefetch request
  } finally {
    isPrefetching = false;
  }
}, 500); // Adjust the debounce timeout as needed

// Call debouncedPrefetch when the search link is clicked

Notes

  • The provided code and environment information suggest a Next.js application with a specific version of React and TypeScript.
  • The issue might be related to the implementation of prefetch in the next package or the application's custom routing logic.

Recommendation

  • Apply a workaround using debouncing to mitigate the issue, as the root cause may be related to the underlying library or framework.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

nextjs - ✅(Solved) Fix Prefetch full refetch the payload if there is already an inflight on Next 16 [1 pull requests, 1 participants]