Skip to content

fix(browser): Ensure user id is consistently added to sessions#19341

Open
Lms24 wants to merge 6 commits intodevelopfrom
lms/fix-browser-session-user
Open

fix(browser): Ensure user id is consistently added to sessions#19341
Lms24 wants to merge 6 commits intodevelopfrom
lms/fix-browser-session-user

Conversation

@Lms24
Copy link
Member

@Lms24 Lms24 commented Feb 16, 2026

This PR fixes multiple bugs and problems around browser sessions, mostly related to user id assignment:

  1. When calling Sentry.setUser() on static pages (i.e. no soft navigations), the user id would never be added to sessions. This is because in static pages, we don't send an "exited" session update. The fix: We send a session update whenever the user is set on the isolationScope (see comment about limitations)

  2. When calling Sentry.setUser() in a single page application (i.e. with soft navigations), we would update the initial session with the user data when starting a new session for a new navigation. However, we did not include the user id on the new session, because the getCurrentScope().getUser() || getIsolationScope().getUser() check was flawed. The fix: we use our getCombinedScopeData helper to get the "correct" (read, consistently like in other telemetry items) user.

  3. It seems like we had an incorrect check that would skip creating a new sessions for the first soft navigation after the pageload (in the default 'route') session lifecycle. The fix: We no longer check for from being undefined.

In addition, I also added a new waitForSession helper and refactored most session integration tests to use this helper. This allows us to more granularly listen to multiple session envelopes simultaneously without running into collision risks.

As a result of these fixes, session counts could increase as a whole but also metrics like "crash free users" will likely change. I added a note to the changelog calling this out.

closes #19317

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

Codecov Results 📊


Generated by Codecov Action

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.61 kB +0.2% +50 B 🔺
@sentry/browser - with treeshaking flags 24.12 kB +0.17% +40 B 🔺
@sentry/browser (incl. Tracing) 42.42 kB +0.14% +57 B 🔺
@sentry/browser (incl. Tracing, Profiling) 47.08 kB +0.11% +50 B 🔺
@sentry/browser (incl. Tracing, Replay) 81.24 kB +0.07% +56 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.86 kB +0.09% +57 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 85.93 kB +0.08% +66 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 98.09 kB +0.07% +60 B 🔺
@sentry/browser (incl. Feedback) 42.33 kB +0.11% +43 B 🔺
@sentry/browser (incl. sendFeedback) 30.28 kB +0.17% +49 B 🔺
@sentry/browser (incl. FeedbackAsync) 35.28 kB +0.16% +56 B 🔺
@sentry/browser (incl. Metrics) 26.78 kB +0.16% +41 B 🔺
@sentry/browser (incl. Logs) 26.92 kB +0.16% +42 B 🔺
@sentry/browser (incl. Metrics & Logs) 27.6 kB +0.16% +42 B 🔺
@sentry/react 27.37 kB +0.14% +37 B 🔺
@sentry/react (incl. Tracing) 44.76 kB +0.09% +38 B 🔺
@sentry/vue 30.06 kB +0.18% +54 B 🔺
@sentry/vue (incl. Tracing) 44.26 kB +0.11% +47 B 🔺
@sentry/svelte 25.64 kB +0.24% +59 B 🔺
CDN Bundle 28.16 kB +0.17% +46 B 🔺
CDN Bundle (incl. Tracing) 43.25 kB +0.11% +47 B 🔺
CDN Bundle (incl. Logs, Metrics) 29 kB +0.16% +45 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 44.09 kB +0.13% +55 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 68.08 kB +0.09% +55 B 🔺
CDN Bundle (incl. Tracing, Replay) 80.12 kB +0.07% +50 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 80.99 kB +0.06% +47 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 85.56 kB +0.08% +61 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.46 kB +0.07% +60 B 🔺
CDN Bundle - uncompressed 82.33 kB +0.15% +118 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 128.05 kB +0.1% +118 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 85.17 kB +0.14% +118 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 130.88 kB +0.1% +118 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 208.83 kB +0.06% +118 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 244.93 kB +0.05% +118 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 247.75 kB +0.05% +118 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 257.73 kB +0.05% +118 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 260.54 kB +0.05% +118 B 🔺
@sentry/nextjs (client) 47.12 kB +0.11% +50 B 🔺
@sentry/sveltekit (client) 42.88 kB +0.16% +68 B 🔺
@sentry/node-core 52.17 kB +0.05% +21 B 🔺
@sentry/node 166.54 kB +0.01% +9 B 🔺
@sentry/node - without tracing 93.96 kB +0.02% +10 B 🔺
@sentry/aws-serverless 109.46 kB +0.01% +5 B 🔺

View base workflow run

@github-actions
Copy link
Contributor

github-actions bot commented Feb 16, 2026

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 9,160 - 11,206 -18%
GET With Sentry 1,564 17% 1,856 -16%
GET With Sentry (error only) 5,854 64% 7,570 -23%
POST Baseline 1,177 - 1,166 +1%
POST With Sentry 562 48% 572 -2%
POST With Sentry (error only) 1,036 88% 1,025 +1%
MYSQL Baseline 3,160 - 3,984 -21%
MYSQL With Sentry 418 13% 515 -19%
MYSQL With Sentry (error only) 2,605 82% 3,288 -21%

View base workflow run

@Lms24 Lms24 changed the title fix(browser): Update session after Sentry.setUser calls fix(browser): Ensure user id is consistently added to sessions Feb 16, 2026
isolationScope.addScopeListener(scope => {
const maybeNewUser = scope.getUser();
// sessions only care about user id and ip address, so we only need to capture the session if the user has changed
if (previousUser?.id !== maybeNewUser?.id || previousUser?.ip_address !== maybeNewUser?.ip_address) {
Copy link

Choose a reason for hiding this comment

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

Scope listener misses user changes with only email/username

Medium Severity

The scope listener condition only checks previousUser?.id and previousUser?.ip_address for changes, but updateSession in session.ts derives the session did from context.user.id || context.user.email || context.user.username. If Sentry.setUser({ email: 'test@test.com' }) is called without an id or ip_address, the listener won't detect the change (both comparisons evaluate to undefined !== undefinedfalse), so captureSession() is never called. The session internally has the did set, but the update is never sent to Sentry. The comment "sessions only care about user id and ip address" doesn't match the actual did derivation logic.

Fix in Cursor Fix in Web

Copy link
Member Author

Choose a reason for hiding this comment

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

That's intentional. The only fields picked from the user are the id and the ip_address (if ever set in the browser). So we only need to watch these for changes.


While we're at it, if you're using Sentry in a Single Page App or meta framework, you might want to give the new `'page'` session lifecycle a try!
This new mode no longer creates a session per soft navigation but continues the initial session until the next hard page refresh.
Check out the [docs](TODO LINK) to learn more!
Copy link
Member

Choose a reason for hiding this comment

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

l: Just a reminder to not forget to set the link in the docs

Copy link
Member

@chargome chargome left a comment

Choose a reason for hiding this comment

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

LGTM

Co-authored-by: Jan Peer Stöcklmair <jan.peer@sentry.io>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.


While we're at it, if you're using Sentry in a Single Page App or meta framework, you might want to give the new `'page'` session lifecycle a try!
This new mode no longer creates a session per soft navigation but continues the initial session until the next hard page refresh.
Check out the [docs](TODO LINK) to learn more!
Copy link

Choose a reason for hiding this comment

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

Placeholder TODO link in changelog entry

Medium Severity

The changelog contains a [docs](TODO LINK) placeholder that hasn't been replaced with an actual URL. This would be published as-is in the release notes, leaving users with a broken/meaningless link.

Fix in Cursor Fix in Web

import: createImport('init'),
gzip: true,
limit: '24.1 KB',
limit: '24.5 KB',
Copy link

Choose a reason for hiding this comment

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

Bundle size increases in browser packages

Low Severity

Multiple browser bundle size limits were increased (e.g., treeshaken build from 24.1 KB to 24.5 KB, CDN bundles up by ~1 KB each). The increases come from adding getIsolationScope, scope listener logic, and getCombinedScopeData import into the session integration. Flagging per project rules — these may be unavoidable given the fix.

Additional Locations (2)

Fix in Cursor Fix in Web

Triggered by project rule: PR Review Guidelines for Cursor Bot

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.

User information no available in the release session

3 participants