Skip to content

GET /index with [slug] dynamic route poisons ISR cache for /, causing permanent 404 #92296

@kesompochy

Description

@kesompochy

Link to the code that reproduces this issue

https://github.com/kesompochy/nextjs-index-bad-cache-reproduction

To Reproduce

  1. npm install && npm run build && npm start
  2. curl http://localhost:3000/ → returns 200
  3. curl http://localhost:3000/index → returns 200 (stale cache)
  4. Wait 2 seconds
  5. 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).

Metadata

Metadata

Assignees

No one assigned

    Labels

    Dynamic RoutesRelated to dynamic routes.Not FoundRelated to the not-found.tsx file or the notFound() function.

    Type

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions