Skip to content

next/link app-router fragment handling in production can append duplicate hashes and restore stale fragments #95551

Description

@timonrey

Link to the code that reproduces this issue

https://github.com/timonrey/next-link-hash-repro

To Reproduce

To Reproduce

  1. Clone the repro repository.
  2. Run npm install.
  3. Run npm run build.
  4. Run npm run start.
  5. Open http://localhost:3100/#section-a.
  6. Click Next hash link to section B.
  7. Open http://localhost:3100/#section-a again.
  8. Click Go to other page with Next pathname string.
  9. On /other, click Back home with Next pathname string.

Current vs. Expected behavior

Current vs. Expected behavior

Current behavior in local production (next build && next start):

  • clicking the next/link hash link from /#section-a produces /#section-a#section-b
  • navigating away from /#section-a with next/link and then returning with a pathname-only next/link restores the stale fragment and lands on /#section-a

Expected behavior:

  • clicking the same-page hash link should replace the fragment and land on /#section-b
  • pathname-only navigation back to / should land on / and should not silently restore the old fragment

Control behavior in the same repro:

  • native hash links correctly land on /#section-b
  • native cross-page navigation correctly returns to /

Provide environment information

### Provide environment information


Operating System:
  Platform: darwin
  Arch: arm64
  Version: macOS
  Available memory (MB): unknown
  Available CPU cores: unknown
Binaries:
  Node: 22.14.0
  npm: 10.9.2
  Yarn: not used in repro
Relevant Packages:
  next: 16.2.6
  react: 19.2.4
  react-dom: 19.2.4
Browser:
  Chromium

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

Linking and Navigating, Route Handlers

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

next build (local), next start (local)

Additional context

Additional context

  • The repro uses the App Router.
  • This issue happens on all browsers
  • The same flows did not reproduce in next dev in this minimal app.
  • The repro includes a small URL debugger that logs pushState, replaceState, hashchange, and popstate.
  • In the duplicate-fragment case, the debugger logs pushState(/#section-a#section-b) even though the clicked link is href="#section-b".

Metadata

Metadata

Assignees

No one assigned

    Labels

    Linking and NavigatingRelated to Next.js linking (e.g., <Link>) and navigation.Route HandlersRelated to Route Handlers.

    Type

    Fields

    No fields configured for Bug.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions