Skip to content

fix(core): Return same value from startSpan as callback returns#19300

Draft
s1gr1d wants to merge 7 commits intodevelopfrom
sig/promise-startspan-types
Draft

fix(core): Return same value from startSpan as callback returns#19300
s1gr1d wants to merge 7 commits intodevelopfrom
sig/promise-startspan-types

Conversation

@s1gr1d
Copy link
Member

@s1gr1d s1gr1d commented Feb 12, 2026

When using startSpan, .then() is called on the callback's return value. This creates another Promise which is a problem in for example jQuery, where the returned Promise does not have the same methods as the jqXHR object.

Closes #19242

@s1gr1d s1gr1d requested a review from isaacs February 12, 2026 14:38
@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

Codecov Results 📊


Generated by Codecov Action

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 2026

size-limit report 📦

Path Size % Change Change
@sentry/browser 25.64 kB +0.29% +72 B 🔺
⛔️ @sentry/browser - with treeshaking flags (max: 24.1 kB) 24.16 kB +0.34% +80 B 🔺
@sentry/browser (incl. Tracing) 42.45 kB +0.2% +81 B 🔺
@sentry/browser (incl. Tracing, Profiling) 47.13 kB +0.21% +97 B 🔺
@sentry/browser (incl. Tracing, Replay) 81.28 kB +0.13% +101 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 70.92 kB +0.17% +118 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 85.97 kB +0.13% +107 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 98.14 kB +0.12% +112 B 🔺
@sentry/browser (incl. Feedback) 42.36 kB +0.18% +75 B 🔺
@sentry/browser (incl. sendFeedback) 30.3 kB +0.24% +71 B 🔺
@sentry/browser (incl. FeedbackAsync) 35.31 kB +0.24% +82 B 🔺
@sentry/browser (incl. Metrics) 26.82 kB +0.31% +82 B 🔺
@sentry/browser (incl. Logs) 26.96 kB +0.32% +84 B 🔺
@sentry/browser (incl. Metrics & Logs) 27.63 kB +0.27% +74 B 🔺
@sentry/react 27.41 kB +0.29% +79 B 🔺
@sentry/react (incl. Tracing) 44.8 kB +0.19% +83 B 🔺
@sentry/vue 30.08 kB +0.24% +70 B 🔺
@sentry/vue (incl. Tracing) 44.3 kB +0.21% +91 B 🔺
@sentry/svelte 25.66 kB +0.29% +74 B 🔺
CDN Bundle 28.2 kB +0.3% +82 B 🔺
CDN Bundle (incl. Tracing) 43.31 kB +0.27% +114 B 🔺
⛔️ CDN Bundle (incl. Logs, Metrics) (max: 29 kB) 29.03 kB +0.28% +80 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 44.13 kB +0.23% +98 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 68.1 kB +0.12% +78 B 🔺
CDN Bundle (incl. Tracing, Replay) 80.14 kB +0.09% +72 B 🔺
⛔️ CDN Bundle (incl. Tracing, Replay, Logs, Metrics) (max: 81 kB) 81.03 kB +0.11% +85 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 85.6 kB +0.12% +98 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 86.48 kB +0.1% +84 B 🔺
CDN Bundle - uncompressed 82.45 kB +0.29% +233 B 🔺
⛔️ CDN Bundle (incl. Tracing) - uncompressed (max: 128 kB) 128.16 kB +0.19% +233 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 85.28 kB +0.28% +233 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 130.99 kB +0.18% +233 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 208.94 kB +0.12% +233 B 🔺
⛔️ CDN Bundle (incl. Tracing, Replay) - uncompressed (max: 245 kB) 245.04 kB +0.1% +233 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 247.86 kB +0.1% +233 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 257.84 kB +0.1% +233 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 260.65 kB +0.09% +233 B 🔺
@sentry/nextjs (client) 47.13 kB +0.19% +89 B 🔺
@sentry/sveltekit (client) 42.91 kB +0.24% +100 B 🔺
@sentry/node-core 52.24 kB +0.18% +90 B 🔺
@sentry/node 166.59 kB +0.05% +81 B 🔺
@sentry/node - without tracing 94.04 kB +0.1% +91 B 🔺
@sentry/aws-serverless 109.54 kB +0.09% +88 B 🔺

View base workflow run

@github-actions
Copy link
Contributor

github-actions bot commented Feb 12, 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,091 - 9,468 -4%
GET With Sentry 1,612 18% 1,662 -3%
GET With Sentry (error only) 6,042 66% 6,035 +0%
POST Baseline 1,193 - 1,179 +1%
POST With Sentry 582 49% 583 -0%
POST With Sentry (error only) 1,037 87% 1,061 -2%
MYSQL Baseline 3,209 - 3,257 -1%
MYSQL With Sentry 452 14% 502 -10%
MYSQL With Sentry (error only) 2,602 81% 2,701 -4%

View base workflow run

@s1gr1d s1gr1d requested review from Lms24 February 12, 2026 15:00
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 1 potential issue.

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

},
);

return value;
Copy link

Choose a reason for hiding this comment

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

Side-effect handlers suppress unhandled promise rejection detection

Medium Severity

Calling value.then(_, onRejected) on the original promise before returning it marks the rejection as "handled" in the JS engine. If the caller of startSpan doesn't handle the rejected promise, no unhandledrejection event fires, silently swallowing the error. Previously, errors would propagate through the .then() chain and surface as unhandled rejections. The onError callback only sets span status — the actual exception is never captured via captureException for plain startSpan usage.

Additional Locations (1)

Fix in Cursor Fix in Web

@isaacs isaacs marked this pull request as draft February 13, 2026 15:27
@isaacs
Copy link
Member

isaacs commented Feb 13, 2026

Converting to a draft, going to push some more commits to try out a slightly different approach to this.

The Remix failures are interesting. Playwright timing out is less interesting, but also could be indicative of a problem, if it's waiting for an expected failure that we're swallowing (haven't dug deeply into it yet).

This might be an acceptable compromise, so long as it doesn't blow up
our bundle size too much.

Copy properties from the original promise onto the chained tracker, so
that we can return something that can inspect the error, does not
obscure `unhandledrejection`, *and* supports jQuery's extended
PromiseLike objects.
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.

startSpan/startSpanManual wraps promise-like objects in a way that’s not reflected by the TypeScript type

2 participants