Link to the code that reproduces this issue
https://github.com/kesompochy/nextjs-index-bad-cache-reproduction
To Reproduce
npm install && npm run build && npm start
curl http://localhost:3000/ → returns 200
curl http://localhost:3000/index → returns 200 (stale cache)
- Wait 2 seconds
curl http://localhost:3000/ → returns 404
Current vs. Expected behavior
Current: After GET /index, GET / permanently returns 404 until the server is restarted.
Expected: GET /index should not affect the ISR cache for /. GET / should continue to return 200.
Provide environment information
Operating System:
Platform: darwin
Arch: arm64
Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:51:28 PST 2026; root:xnu-12377.91.3~2/RELEASE_ARM64_T6041
Available memory (MB): 49152
Available CPU cores: 12
Binaries:
Node: 24.14.0
npm: 11.9.0
Yarn: N/A
pnpm: N/A
Relevant Packages:
next: 16.2.1-canary.18 // Latest available version is detected (16.2.1-canary.18).
eslint-config-next: N/A
react: 19.2.4
react-dom: 19.2.4
typescript: 5.9.3
Next.js Config:
output: N/A
Which area(s) are affected? (Select all that apply)
Dynamic Routes, Not Found
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
This was discovered as a production incident in a Kubernetes (self-hosted) environment. An external client requested GET /index, which poisoned the ISR cache on all pods and caused the home page to return 404.
From reading the source code, I believe the root cause is that resolvedPathname is used for both URL canonicalization (/index → / at route-module.ts) and as the ISR cache key (ssgCacheKey). When /index is handled by [slug], its notFound() result overwrites the / cache entry. There is a comment at base-server.ts that acknowledges this collision but it is not guarded against in the ISR cache write path.
Reproduction conditions:
/ page with ISR (revalidate > 0)
- Root-level
[slug] with dynamicParams: true
[slug] calls notFound() for unknown slugs
Confirmed on both Next.js 16.2.1 and canary (16.2.1-canary.18).
Link to the code that reproduces this issue
https://github.com/kesompochy/nextjs-index-bad-cache-reproduction
To Reproduce
npm install && npm run build && npm startcurl http://localhost:3000/→ returns 200curl http://localhost:3000/index→ returns 200 (stale cache)curl http://localhost:3000/→ returns 404Current vs. Expected behavior
Current: After
GET /index,GET /permanently returns 404 until the server is restarted.Expected:
GET /indexshould not affect the ISR cache for/.GET /should continue to return 200.Provide environment information
Operating System: Platform: darwin Arch: arm64 Version: Darwin Kernel Version 25.3.0: Wed Jan 28 20:51:28 PST 2026; root:xnu-12377.91.3~2/RELEASE_ARM64_T6041 Available memory (MB): 49152 Available CPU cores: 12 Binaries: Node: 24.14.0 npm: 11.9.0 Yarn: N/A pnpm: N/A Relevant Packages: next: 16.2.1-canary.18 // Latest available version is detected (16.2.1-canary.18). eslint-config-next: N/A react: 19.2.4 react-dom: 19.2.4 typescript: 5.9.3 Next.js Config: output: N/AWhich area(s) are affected? (Select all that apply)
Dynamic Routes, Not Found
Which stage(s) are affected? (Select all that apply)
next start (local), Other (Deployed)
Additional context
This was discovered as a production incident in a Kubernetes (self-hosted) environment. An external client requested
GET /index, which poisoned the ISR cache on all pods and caused the home page to return 404.From reading the source code, I believe the root cause is that
resolvedPathnameis used for both URL canonicalization (/index→/at route-module.ts) and as the ISR cache key (ssgCacheKey). When/indexis handled by[slug], itsnotFound()result overwrites the/cache entry. There is a comment at base-server.ts that acknowledges this collision but it is not guarded against in the ISR cache write path.Reproduction conditions:
/page with ISR (revalidate > 0)[slug]withdynamicParams: true[slug]callsnotFound()for unknown slugsConfirmed on both Next.js 16.2.1 and canary (16.2.1-canary.18).