Skip to content

Conversation

@logaretm
Copy link
Collaborator

@logaretm logaretm commented Nov 12, 2025

Summary

ISR pages will have a sentry-trace and baggage meta tags rendered on them following the initial render or after the first invalidation causing a cached trace id to be present until the next invalidation.

This happens in Next.js 15/16 and both on Turbopack and Webpack.

What I tried and didn't work

I Found no way to conditionally set/unset/change the values set by the clientTraceMetadata option, I found nothing useful on unit async storages, nor re-setting the propagation context works. The clientTraceMetadata gets called way earlier at the app-render.tsx level, which would call our SentryPropagator.inject() then. We cannot intercept it either because it runs before the page wrapper is called.

The main issue is timing:

  • Suppressing the tracing wouldn't work either because it is too late. Ideally we want a way to tell Next to remove those attributes at runtime, or render them conditionally.
  • I also tried setting everything that has to do with sentry-trace or baggage to dummy values as some sort of "marker" for the SDK on the browser side to drop them, but again it is too late since clientTraceMetadata is picked up too early.

Implementation

so I figured a workaround, I decided to do it on the client side by:

  • Marking ISR page routes via the route manifest we already have.
  • In Sentry.init call we remove the tags before the browser integration has had a chance to grab the meta tags.

Not the cleanest way, but I verified the issue by writing tests for it and observing page loads across multiple page visits having the same trace id. The meta deletion forces them to have new id for every visit which is what we want.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 12, 2025

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 24.62 kB - -
@sentry/browser - with treeshaking flags 23.13 kB - -
@sentry/browser (incl. Tracing) 41.28 kB - -
@sentry/browser (incl. Tracing, Profiling) 45.61 kB - -
@sentry/browser (incl. Tracing, Replay) 79.73 kB - -
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 69.44 kB - -
@sentry/browser (incl. Tracing, Replay with Canvas) 84.43 kB - -
@sentry/browser (incl. Tracing, Replay, Feedback) 96.64 kB - -
@sentry/browser (incl. Feedback) 41.29 kB - -
@sentry/browser (incl. sendFeedback) 29.29 kB - -
@sentry/browser (incl. FeedbackAsync) 34.21 kB - -
@sentry/react 26.32 kB - -
@sentry/react (incl. Tracing) 43.22 kB - -
@sentry/vue 29.11 kB - -
@sentry/vue (incl. Tracing) 43.08 kB - -
@sentry/svelte 24.64 kB - -
CDN Bundle 26.94 kB - -
CDN Bundle (incl. Tracing) 41.83 kB - -
CDN Bundle (incl. Tracing, Replay) 78.38 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) 83.85 kB - -
CDN Bundle - uncompressed 78.92 kB - -
CDN Bundle (incl. Tracing) - uncompressed 124.07 kB - -
CDN Bundle (incl. Tracing, Replay) - uncompressed 240.1 kB - -
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 252.87 kB - -
@sentry/nextjs (client) 45.5 kB +0.3% +136 B 🔺
@sentry/sveltekit (client) 41.67 kB - -
@sentry/node-core 50.91 kB - -
@sentry/node 159.09 kB - -
@sentry/node - without tracing 92.78 kB +0.01% +1 B 🔺
@sentry/aws-serverless 106.53 kB +0.01% +1 B 🔺

View base workflow run

@logaretm logaretm force-pushed the awad/js-1152-nextjs-incremental-static-rendering-causes-cached-trace-id branch from 73ec1ba to 54be3bf Compare November 12, 2025 20:38
@logaretm logaretm marked this pull request as ready for review November 13, 2025 10:05
@logaretm logaretm requested a review from chargome November 13, 2025 10:06
@logaretm logaretm requested a review from Lms24 November 13, 2025 10:38
@logaretm logaretm force-pushed the awad/js-1152-nextjs-incremental-static-rendering-causes-cached-trace-id branch from 289f39c to 12badfa Compare November 13, 2025 19:10
@logaretm logaretm force-pushed the awad/js-1152-nextjs-incremental-static-rendering-causes-cached-trace-id branch from 12badfa to f46d817 Compare November 17, 2025 09:00
@github-actions
Copy link
Contributor

github-actions bot commented Nov 17, 2025

node-overhead report 🧳

Note: This is a synthetic benchmark with a minimal express app and does not necessarily reflect the real-world performance impact in an application.

Scenario Requests/s % of Baseline Prev. Requests/s Change %
GET Baseline 8,897 - 9,044 -2%
GET With Sentry 1,365 15% 1,345 +1%
GET With Sentry (error only) 6,149 69% 6,076 +1%
POST Baseline 1,181 - 1,103 +7%
POST With Sentry 481 41% 465 +3%
POST With Sentry (error only) 1,037 88% 945 +10%
MYSQL Baseline 3,340 - 3,151 +6%
MYSQL With Sentry 503 15% 413 +22%
MYSQL With Sentry (error only) 2,737 82% 2,602 +5%

View base workflow run

/**
* Check if the current page is an ISR/SSG route by checking the route manifest.
*/
function isIsrSsgRoute(pathname: string): boolean {
Copy link
Member

Choose a reason for hiding this comment

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

Do you think we should cache the results of this function? Esp as it's calling a JSON.parse of the route manifest?

Copy link
Collaborator Author

@logaretm logaretm Nov 17, 2025

Choose a reason for hiding this comment

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

I think that's a good idea since the manifest shouldn't change in runtime 👍 I can see we already use getManifest which caches the JSON parsing. I will create another cache as well for the route matcher rather than the actual pathname since it may get a lot of entries.


// Remove cached trace meta tags for ISR/SSG pages before initializing
// This prevents the browser tracing integration from using stale trace IDs
removeIsrSsgTraceMetaTags();
Copy link
Member

Choose a reason for hiding this comment

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

this should be gated behind the if (typeof __SENTRY_TRACING__ === 'undefined' || __SENTRY_TRACING__) { flag like adding the browserTracingIntegration is.

@logaretm logaretm force-pushed the awad/js-1152-nextjs-incremental-static-rendering-causes-cached-trace-id branch from 5dddf30 to a49edb2 Compare November 17, 2025 16:40
const content = fs.readFileSync(pageFilePath, 'utf8');
// check for generateStaticParams export
// the regex covers `export function generateStaticParams`, `export async function generateStaticParams`, `export const generateStaticParams`
return /export\s+(async\s+)?function\s+generateStaticParams|export\s+const\s+generateStaticParams/.test(content);
Copy link

Choose a reason for hiding this comment

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

Bug: Fix Regex Over-Matching

The regex pattern matching generateStaticParams lacks word boundaries, causing false positives. It will incorrectly match identifiers like generateStaticParamsFoo or generateStaticParamsExtra because the pattern doesn't verify where the identifier ends. Add \b word boundaries after generateStaticParams in both alternations to match only the exact export name.

Fix in Cursor Fix in Web

* Cache for ISR/SSG route checks. Exported for testing purposes.
* @internal
*/
export const IS_ISR_SSG_ROUTE_CACHE = new Map<string, boolean>();
Copy link
Member

Choose a reason for hiding this comment

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

This should be an LRUMap

Copy link
Collaborator Author

@logaretm logaretm Nov 17, 2025

Choose a reason for hiding this comment

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

Oh, I didn't see that 🤦‍♂️ I will amend in a PR.

@logaretm logaretm merged commit 1679d80 into develop Nov 17, 2025
62 checks passed
@logaretm logaretm deleted the awad/js-1152-nextjs-incremental-static-rendering-causes-cached-trace-id branch November 17, 2025 18:04
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.

nextjs incremental static rendering causes cached trace id, leading to merged client-side transactions from different users/requests

3 participants