FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(nextjs): Never emit trace meta tags from a prerender by chargome · Pull Request #25141 · getsentry/sentry-javascript · GitHub

Repository navigation

feat(nextjs): Never emit trace meta tags from a prerender - #25141

Draft
chargome wants to merge 6 commits into
developfrom
chargome/feat/nextjs-prerender-trace-guard
Draft

chargome wants to merge 6 commits into
developfrom
chargome/feat/nextjs-prerender-trace-guard

Conversation

chargome commented Oct 7, 2026 •
edited
Loading

Copy link
Copy Markdown
Member

Under cacheComponents the SDK did not enable experimental.clientTraceMetadata (#21141). A shell that Next.js prerenders during one request is cached and served to later visitors, and a sentry-trace tag inside it would attach all of them to that one request. ISR pages had the same problem, worked around on the client by removing the tags on routes with generateStaticParams (#18192).

Next.js computes the trace tags of a document inside the prerender route (app) span when it prerenders, and outside of it when it renders for a request, including when it resumes a shell. The server SDK now marks that span on the OpenTelemetry context, and its propagator hands out nothing on a marked context. A prerendered shell never contains a trace, so any tag that reaches the browser belongs to the current request. The mark sits on the context rather than the span because an unsampled request makes the span non-recording, with no attributes to recognize it by, and a sampled=0 tag in the shell would drop every later pageload. Checked in Next.js 15.0 through 16.4.

With that, clientTraceMetadata is enabled again under cacheComponents, and the client-side ISR workaround and the isrRoutes manifest field are removed. The guard covers ISR shells too, including revalidate routes the file scan never found.

The guard is applied to the tracer provider and propagator the Node SDK registers, and withSentry of @sentry/nextjs/cloudflare applies it to its own setup, since ISR pages revalidate inside a request of the Worker. A custom OpenTelemetry setup such as @vercel/otel is left as is and does not get the guard.

An ISR page with revalidate = 1 makes the e2e suite exercise the guard at runtime; the other ISR shells come from the build, where the SDK does not run.

On its own this PR keeps the current client behaviour: tags in <head> are continued and are now always fresh. The tag of a resumed shell arrives with the resumed part, which the client only reads in #25142.

Refs #24944, see #24298

chargome commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

bugbot run

1 similar comment

chargome commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

bugbot run

cursor Bot left a comment •
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Stale Bugbot comment from a previous run.

chargome commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

bugbot run

chargome force-pushed the chargome/feat/nextjs-prerender-trace-guard branch from 33c6ae1 to feab86e Compare October 8, 2026 07:58

chargome commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

bugbot run

cursor Bot left a comment •
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Stale Bugbot comment from a previous run.

chargome commented Oct 8, 2026

Copy link
Copy Markdown
Member Author

bugbot run

cursor Bot left a comment •
edited
Loading

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Stale Bugbot comment from a previous run.

github-actions Bot commented Oct 8, 2026 •
edited
Loading

Copy link
Copy Markdown
Contributor

size-limit report 📦

⚠️ Warning: Base artifact is not the latest one, because the latest workflow run is not done yet. This may lead to incorrect results. Try to re-run all tests to get up to date results.

Path Size % Change Change
@sentry/browser 29.82 kB - -
@sentry/browser - with treeshaking flags 27.96 kB - -
@sentry/browser - with treeshaking flags tracing without tracing 27.87 kB - -
@sentry/browser (incl. Tracing) 51.89 kB - -
@sentry/browser (incl. Tracing + Span Streaming) 51.91 kB - -
@sentry/browser (incl. Tracing, Profiling) 54.84 kB - -
@sentry/browser (incl. Tracing, Replay) 91.64 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 80.51 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 96.36 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 109.34 kB - -
@sentry/browser (incl. Feedback) 47.35 kB - -
@sentry/browser (incl. sendFeedback) 34.87 kB - -
@sentry/browser (incl. FeedbackAsync) 39.98 kB - -
@sentry/browser (incl. Metrics) 30.85 kB - -
@sentry/browser (incl. Logs) 31.14 kB - -
@sentry/browser (incl. Metrics & Logs) 31.78 kB - -
@sentry/react 31.66 kB - -
@sentry/react (incl. Tracing) 54.22 kB - -
@sentry/vue 37.89 kB - -
@sentry/vue (incl. Tracing) 54.81 kB - -
@sentry/svelte 29.85 kB - -
@sentry/remix (Remix 3 client bundle) 56.88 kB - -
CDN Bundle 31.57 kB - -
CDN Bundle (incl. Tracing) 52.4 kB - -
CDN Bundle (incl. Logs, Metrics) 33.76 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) 54.35 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) 74.68 kB - -
CDN Bundle (incl. Tracing, Replay) 90.07 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 92.01 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 96.23 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 98.2 kB - -
CDN Bundle - uncompressed 93.05 kB - -
CDN Bundle (incl. Tracing) - uncompressed 155.64 kB - -
CDN Bundle (incl. Logs, Metrics) - uncompressed 99.59 kB - -
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 161.59 kB - -
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 229.63 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 275.8 kB - -
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 281.74 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 289.51 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 295.44 kB - -
@sentry/nextjs (client) 56.45 kB -0.25% -137 B 🔽
@sentry/sveltekit (client) 52.27 kB - -
@sentry/core/server 40.87 kB - -
@sentry/core/browser 13.73 kB - -
@sentry/node 151.69 kB +0.01% +3 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 83.77 kB - -
@sentry/node - without tracing 94.25 kB +0.01% +9 B 🔺
@sentry/node - without channel injection 129.86 kB +0.01% +7 B 🔺
@sentry/aws-serverless 102.42 kB +0.01% +1 B 🔺
@sentry/cloudflare (withSentry) - minified 210.01 kB - -
@sentry/cloudflare (withSentry) 520.66 kB - -
@sentry/nextjs/cloudflare (withSentry) - minified 228.95 kB +0.57% +1.27 kB 🔺

View base workflow run

chargome and others added 6 commits October 9, 2026 16:13
Under cacheComponents the SDK stopped enabling clientTraceMetadata, because
a shell that Next.js prerenders inside one request is cached and served to
later visitors, and a sentry-trace tag baked into it would replay that
request's trace to all of them. ISR pages had the same problem, patched on
the client by removing the tags on generateStaticParams routes.

Next.js computes a document's trace tags inside the "prerender route (app)"
span when it prerenders and outside of it when it renders for a request,
including the resume of a shell. Register a SentryPropagator subclass that
hands out no trace context while that span is active, so a prerendered
shell never contains a trace and any tag that reaches the browser belongs
to the current request. Only swap the propagator when the Node SDK
registered its own, so a foreign OpenTelemetry setup stays untouched.

Enable clientTraceMetadata again under cacheComponents and remove the
client-side ISR heuristic together with the isrRoutes manifest field. The
guard covers ISR shells as well, including revalidate routes without
generateStaticParams.

Refs #24944
Refs JS-3863
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The turbopack dev variant runs with TEST_ENV=dev-turbopack, which the
development check did not match, so the tags-absent assertions ran against
a dev render where the tags are fresh and kept.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Next.js computes a document's trace meta tags at the top of its prerender
function, inside the span it wraps the prerender in. Recognizing that span by
its attributes fails when the request is not sampled: the span is then
non-recording and has no attributes, so the propagator still wrote a
`sampled=0` tag into the cached shell, and every later visitor inherited the
negative decision. A span nested in the prerender would have passed the check
as well.

Mark the prerender on the OpenTelemetry context instead, through the tracer
provider the Node SDK registered, and have the propagator skip a marked
context. The mark is inherited by everything that runs inside the prerender
and exists whether or not the span records.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… caller

Next.js starts its spans through `startActiveSpan`, which the tracer wrapper
marks on the context. A span started through `startSpan` and set on a context
by the caller takes a different path, so the wrapper remembers those spans and
the propagator checks the span on the context too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…flare

ISR pages revalidate inside a request of the Worker, where `withSentry` of
`@sentry/nextjs/cloudflare` registers its own tracer provider and propagator.
The guard only covered the setup of the Node SDK, so a shell prerendered in
the Worker got that request's trace. The Next.js integration now marks
prerenders on the tracer provider `@sentry/cloudflare` registered and its
propagator skips a marked context.

Also moves the changelog entry above the contributor line and fixes a test
comment that pointed to a file of the follow-up PR.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The ISR shells of the e2e apps come from the build, where the SDK does not
run, so the tag assertions passed with or without the guard. A page with a
one second window makes the server prerender it again inside a request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
chargome force-pushed the chargome/feat/nextjs-prerender-trace-guard branch from cf27bae to 576a529 Compare October 9, 2026 14:24

chargome commented Oct 9, 2026

Copy link
Copy Markdown
Member Author

bugbot run

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.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

✅ 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 576a529. Configure here.

This branch has not been deployed

No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
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.

1 participant


Back | FazBrowse Home | New Git URL