@netlify/plugin-nextjs@4.41.5 ODB routing conflict with catch-all route and causing dynamic route to be served from cache.
Environment
- Next.js 14 (14.2.35)
- App Router
- @netlify/plugin-nextjs version "^4.41.3",
- Deployed on Netlify
Reproduction
This is a minimal project to reproduce the reported behavior:
https://github.com/dunfe/netlify-next-first-user-cache-repro/tree/main
Netflix url: https://netlify-next-first-user-cache-repro.netlify.app/
Video: https://github.com/dunfe/netlify-next-first-user-cache-repro/blob/main/output.mp4
- /dashboard is a dynamic App Router page (ƒ).
- It reads the current user from the user cookie on every SSR render.
- app/[...slug]/page.tsx is an App Router SSG catch-all route. When Contentful is healthy it renders generated child pages; when simulated Contentful connection fails, it still appears as ● /[...slug] without child paths.
- A simulated Contentful build failure is enabled with SIMULATE_CONTENTFUL_FAILURE=1.
- When that flag is enabled, middleware adds a cacheable Cache-Control header to /dashboard.
- On Netlify, the Next adapter/runtime can promote that response to Netlify-CDN-Cache-Control: ..., durable while the default Netlify-Vary does not vary by auth cookie.
- Result: the first user to hit /dashboard after deploy can seed the cached dashboard response for later users.
- This project is pinned to Next.js 14.2.35 and @netlify/plugin-nextjs 4.41.5 to test the older runtime where the issue was reported.
Reproduce with browser
After the deploy is live, test client-side navigation, not only direct hard-refresh document loads.
- Open a fresh browser profile as user A.
- Visit / first.
- Type A in the User name text box.
- Click Login as user. The form sets document.cookie = 'user=A; Path=/; SameSite=Lax' and performs an App Router router.push('/dashboard') without a hard refresh.
- Open another browser/profile as user B.
- Visit / first.
- Type B in the User name text box.
- Click Login as user.
- You can also switch users from the manual login section on /dashboard; it updates the user cookie and refreshes the route without opening browser devtools.
OBSERVED BEHAVIOR:
- User B request has Cookie: user=B.
- The browser RSC request for /dashboard?_rsc=... can return user A's RSC payload if A was first.
- Direct document requests to /dashboard may still look correct because the leak is in the App Router RSC/flight payload.
- If B is first after deploy, A later sees B.
NOTE:
Expected Behavior
Since /dashboard is a dynamic route, there should be no cache content served.
@netlify/plugin-nextjs@4.41.5 ODB routing conflict with catch-all route and causing dynamic route to be served from cache.
Environment
Reproduction
This is a minimal project to reproduce the reported behavior:
https://github.com/dunfe/netlify-next-first-user-cache-repro/tree/main
Netflix url: https://netlify-next-first-user-cache-repro.netlify.app/
Video: https://github.com/dunfe/netlify-next-first-user-cache-repro/blob/main/output.mp4
Reproduce with browser
After the deploy is live, test client-side navigation, not only direct hard-refresh document loads.
OBSERVED BEHAVIOR:
NOTE:
Expected Behavior
Since /dashboard is a dynamic route, there should be no cache content served.