Skip to content

fix(nextjs): Keep router.back/forward navigation type under span streaming - #24074

Open
chargome wants to merge 3 commits into
developfrom
nextjs-router-navigation
Open

fix(nextjs): Keep router.back/forward navigation type under span streaming#24074
chargome wants to merge 3 commits into
developfrom
nextjs-router-navigation

Conversation

@chargome

@chargome chargome commented Sep 4, 2026

Copy link
Copy Markdown
Member

Under span streaming, ignoreSpans is applied at span start. The placeholder span that router.back()/router.forward() started in router-patch mode was therefore non-recording, and popstate created a second span tagged browser.popstate instead of renaming it.

back()/forward() now record the router method and timestamp, and the popstate listener starts the navigation span with that navigation.type and startTime. The placeholder name and its ignoreSpans entry are removed, and the two E2E tests skipped in #23905 are re-enabled.

Fixes #23909

…aming

In router-patch mode, router.back() and router.forward() started a
navigation span with a placeholder name that the popstate listener
renamed later. With span streaming, ignoreSpans is applied when a span
starts, so the placeholder span was non-recording from the start and
popstate fell through to creating a second span tagged browser.popstate.

Instead of the placeholder span, remember the router method and its
timestamp, and start the navigation span from the popstate event with
that navigation type and start time. This keeps the span starting at the
router call, works for both trace lifecycles, and no longer records an
ignored-span client outcome per traversal. A pending traversal expires
after one second so a back()/forward() with no matching history entry
cannot be attributed to a later unrelated popstate.

The placeholder name and its ignoreSpans entry are removed since nothing
produces such spans anymore.

Fixes #23909
Refs JS-3527
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@linear-code

linear-code Bot commented Sep 4, 2026

Copy link
Copy Markdown

JS-3527

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.69 kB - -
@sentry/browser - with treeshaking flags 26.99 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 26.89 kB - -
@sentry/browser (incl. Tracing) 49.07 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 49.07 kB - -
@sentry/browser (incl. Tracing, Profiling) 51.98 kB - -
@sentry/browser (incl. Tracing, Replay) 88.62 kB +0.08% +64 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.85 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 93.3 kB +0.07% +61 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 106.24 kB +0.06% +60 B 🔺
@sentry/browser (incl. Feedback) 46.17 kB - -
@sentry/browser (incl. sendFeedback) 33.75 kB - -
@sentry/browser (incl. FeedbackAsync) 38.85 kB - -
@sentry/browser (incl. Metrics) 29.66 kB - -
@sentry/browser (incl. Logs) 29.94 kB - -
@sentry/browser (incl. Metrics & Logs) 30.59 kB - -
@sentry/react 30.45 kB - -
@sentry/react (incl. Tracing) 51.28 kB - -
@sentry/vue 35.91 kB - -
@sentry/vue (incl. Tracing) 51.34 kB - -
@sentry/svelte 28.71 kB - -
CDN Bundle 30.43 kB - -
CDN Bundle (incl. Tracing) 49.6 kB - -
CDN Bundle (incl. Logs, Metrics) 32.66 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 51.53 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 73.31 kB +0.09% +61 B 🔺
CDN Bundle (incl. Tracing, Replay) 87.15 kB +0.07% +55 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 89.02 kB +0.06% +53 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 93.08 kB +0.07% +57 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 95.03 kB +0.07% +58 B 🔺
CDN Bundle - uncompressed 90.13 kB - -
CDN Bundle (incl. Tracing) - uncompressed 147.81 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 96.52 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 153.59 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 225.82 kB +0.07% +142 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 267.44 kB +0.06% +142 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 273.21 kB +0.06% +142 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 281.15 kB +0.06% +142 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 286.9 kB +0.05% +142 B 🔺
@sentry/nextjs (client) 53.87 kB -0.03% -16 B 🔽
@sentry/sveltekit (client) 49.51 kB - -
@sentry/core/server 40.96 kB - -
@sentry/core/browser 13.53 kB - -
@sentry/node 124.76 kB +0.1% +123 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.51 kB - -
@sentry/node - without tracing 88.5 kB +0.03% +23 B 🔺
@sentry/node - without channel injection 104.08 kB +0.15% +154 B 🔺
@sentry/aws-serverless 96.87 kB +0.03% +23 B 🔺
@sentry/cloudflare (withSentry) - minified 201.56 kB - -
@sentry/cloudflare (withSentry) 501.37 kB - -

View base workflow run

@chargome chargome self-assigned this Sep 4, 2026
A timestamp comparison misattributed the popstate when the main thread
was blocked between router.back() and the event, since the delay counts
against wall-clock age. A timer is delayed by the same block, which is
how the previous placeholder span's idle timeout behaved.

Also cover the branch that starts a fresh span when back() is called
while a push() span is still open.

Refs JS-3527
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chargome

chargome commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

bugbot run

Comment thread packages/nextjs/test/client/appRouterRoutingInstrumentation.test.ts
Spans started from popstate built their URL from the pathname alone,
so router.back()/forward() lost the query string in url.full that the
previous update path preserved from location.href. Pass the full
location instead, which also aligns plain browser.popstate spans.

Drive the traversal expiry test with fake timers instead of a real sleep.

Refs JS-3527
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chargome

chargome commented Sep 4, 2026

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 25cf59a. Configure here.

@chargome
chargome marked this pull request as ready for review September 4, 2026 12:37
@chargome
chargome requested a review from a team as a code owner September 4, 2026 12:37
@chargome
chargome requested review from RulaKhaled, logaretm, mydea and s1gr1d and removed request for a team and mydea September 4, 2026 12:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Next.js app router: router.back()/router.forward() navigations are tagged browser.popstate under span streaming

1 participant