vercel / vercel/next.js

`router.push()` reuses cached redirect from prefetch without fresh middleware evaluation

Open
#88,937 1 comment 8 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

linear: next Linking and Navigating Middleware
Dominant language
JavaScript
Stars
142k
Forks
32.5k
Avg merge
2d 14h
Merged PRs (30d)
351

Description

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

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the linked reproduction and trace the interaction between the Link prefetch, middleware redirect, and router.push('/'). Compare the cached redirect path with the expected fresh request after the processingComplete cookie changes; done means navigation reaches / and middleware re-evaluates instead of reusing the stale redirect.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, next.js, react
Domain
web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.