nextjs - ✅(Solved) Fix `router.push()` reuses cached redirect from prefetch without fresh middleware evaluation [1 pull requests, 1 comments, 2 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#88937Fetched 2026-04-08 02:03:39
View on GitHub
Comments
1
Participants
2
Timeline
8
Reactions
5
Timeline (top)
labeled ×3referenced ×2commented ×1cross-referenced ×1

Root Cause

  1. Navigate to /process page (no cookie set)
  2. Page renders with a sidebar containing <Link href="/">Dashboard</Link>
  3. Next.js automatically prefetches the / route
  4. Middleware evaluates and returns 307 redirect to /process (because cookie is false)
  5. Click "Start Process" button which:
    • Performs async work (simulated 2 seconds)
    • Sets cookie: processingComplete=true
    • Calls router.push('/') to navigate to dashboard
  6. Observe: User stuck on /process page, no navigation occurs

Fix Action

Fix / Workaround

Workarounds:

PR fix notes

PR #89618: fix(segment-cache): bypass cache for middleware redirect responses #88937

Description (problem / solution / changelog)

What?

This PR makes middleware redirect responses immediately stale in the segment cache, ensuring middleware is re-evaluated on subsequent navigations.

Why?

When a middleware redirect is prefetched, the route cache entry is stored with a 5-minute stale time (STATIC_STALETIME_MS). This causes a bug where:

1.User visits / → middleware redirects to /process (prefetch cached) 2.User completes processing, cookie is set 3.User clicks link to / → cached redirect is reused, middleware NOT re-evaluated 4.User stuck in redirect loop despite state change

Users expect middleware to evaluate fresh on each navigation. The current caching behavior violates this expectation for redirects.

How?

Added an isRedirect parameter that flows through the caching chain: fetchRouteOnCacheMiss (response.redirected available) → discoverKnownRoute(isRedirect) → discoverKnownRoutePart(isRedirect) → writeRouteIntoCache(isRedirect) → fulfillRouteCacheEntry(isRedirect) → staleAt = isRedirect ? now : now + STATIC_STALETIME_MS

Key change:

// cache.ts line 1047
fulfilledEntry.staleAt = isRedirect ? now : now + STATIC_STALETIME_MS

Non-redirect responses are unaffected (default isRedirect=false).

Closes NEXT- Fixes #88937

Changed files

  • packages/next/src/client/components/segment-cache/cache.ts (modified, +13/-7)
  • packages/next/src/client/components/segment-cache/optimistic-routes.ts (modified, +18/-9)

Code Example

router.refresh();
await new Promise(resolve => setTimeout(resolve, 100));
router.push('/');
RAW_BUFFERClick to expand / collapse

Link to the code that reproduces this issue

https://github.com/KumarNitin19/nextjs-prefetch-redirect-bug

To Reproduce

I'm running middleware that conditionally redirects based on a cookie value. The / route is protected and redirects to /process when the processingComplete cookie is not set.

Steps to Reproduce:

  1. Navigate to /process page (no cookie set)
  2. Page renders with a sidebar containing <Link href="/">Dashboard</Link>
  3. Next.js automatically prefetches the / route
  4. Middleware evaluates and returns 307 redirect to /process (because cookie is false)
  5. Click "Start Process" button which:
    • Performs async work (simulated 2 seconds)
    • Sets cookie: processingComplete=true
    • Calls router.push('/') to navigate to dashboard
  6. Observe: User stuck on /process page, no navigation occurs

Live Demo (Vercel): https://nextjs-prefetch-redirect-bug.vercel.app/

Current vs. Expected behavior

Expected: When router.push('/') is called after the cookie changes:

  • Fresh GET request should be made to /
  • Middleware should re-evaluate with new cookie value
  • Middleware should allow navigation (no redirect)
  • User navigates to Dashboard

Current:

  • No fresh request is made to /
  • Router reuses the cached redirect from initial prefetch
  • Middleware is never re-evaluated
  • User stuck on /process page

The router appears to cache the redirect response from the prefetch and reuses it on router.push() without checking if the state has changed.

Provide environment information

Relevant Packages:

  • next: 15.5.8 (also tested on 15.5.9, bug reproduces on both)
  • react: 19.1.0
  • react-dom: 19.1.0
  • typescript: ^5

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

Linking and Navigating, Middleware

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

Vercel (Deployed), Other (Deployed), next build (local)

Additional context

Workarounds:

  1. Disable prefetch (works reliably): <Link href="/" prefetch={false}>Dashboard</Link>

  2. Hard navigation (works reliably): window.location.href = '/';

  3. Router refresh before push (unreliable):

router.refresh();
await new Promise(resolve => setTimeout(resolve, 100));
router.push('/');

Impact:

This affects any route where NextResponse.redirect() was previously returned by middleware. Once the redirect is cached from a prefetch, subsequent router.push() calls to that route will reuse the cached redirect without re-evaluating middleware logic, even if the application state has changed.

Common scenarios affected:

  • Onboarding/signup flows with step-based redirects
  • Authentication state transitions
  • Feature flag-based routing

extent analysis

TL;DR

Disable prefetch on links that may be affected by middleware redirects to prevent cached redirect responses from interfering with navigation.

Guidance

  • Identify routes that use NextResponse.redirect() in middleware and may be prefetched, and consider disabling prefetch on links to these routes using prefetch={false}.
  • Alternatively, use hard navigation with window.location.href instead of router.push() for routes that are known to be affected by this issue.
  • Be cautious when using router.refresh() as a workaround, as it may not be reliable in all scenarios.
  • Consider the impact of this issue on common scenarios such as onboarding flows, authentication state transitions, and feature flag-based routing.

Example

// Disable prefetch on link to prevent cached redirect
<Link href="/" prefetch={false}>Dashboard</Link>

Notes

This issue appears to be related to how Next.js caches redirect responses from middleware, and disabling prefetch or using hard navigation can help mitigate the problem. However, a more robust solution may require changes to how middleware redirects are handled in Next.js.

Recommendation

Apply workaround by disabling prefetch on affected links, as this is a reliable solution that can help prevent cached redirect responses from interfering with navigation.

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