Skip to content

feat(core): Record callback_error client reports for throwing user callbacks - #23903

Open
msonnb wants to merge 3 commits into
developfrom
ms/callback-error-drop-reason
Open

feat(core): Record callback_error client reports for throwing user callbacks#23903
msonnb wants to merge 3 commits into
developfrom
ms/callback-error-drop-reason

Conversation

@msonnb

@msonnb msonnb commented Sep 2, 2026

Copy link
Copy Markdown
Member

Drops caused by a throwing user callback were reported with the same client report reason as a legitimate filter. They now use a new callback_error reason so the two are distinguishable.

Part of #23755

@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

size-limit report 📦

Path Size % Change Change
@sentry/browser 28.79 kB +0.37% +106 B 🔺
@sentry/browser - with treeshaking flags 27.1 kB +0.39% +103 B 🔺
@sentry/browser - with treeshaking flags tracing without tracing 26.99 kB +0.4% +107 B 🔺
@sentry/browser (incl. Tracing) 49.21 kB +0.28% +137 B 🔺
@sentry/browser (incl. Tracing + Span Streaming) 49.21 kB +0.29% +139 B 🔺
@sentry/browser (incl. Tracing, Profiling) 52.11 kB +0.26% +131 B 🔺
@sentry/browser (incl. Tracing, Replay) 88.75 kB +0.16% +134 B 🔺
@sentry/browser (incl. Tracing, Replay) - with treeshaking flags 77.94 kB +0.12% +93 B 🔺
@sentry/browser (incl. Tracing, Replay with Canvas) 93.43 kB +0.15% +133 B 🔺
@sentry/browser (incl. Tracing, Replay, Feedback) 106.36 kB +0.12% +119 B 🔺
@sentry/browser (incl. Feedback) 46.29 kB +0.25% +115 B 🔺
@sentry/browser (incl. sendFeedback) 33.85 kB +0.31% +104 B 🔺
@sentry/browser (incl. FeedbackAsync) 38.97 kB +0.3% +116 B 🔺
@sentry/browser (incl. Metrics) 29.81 kB +0.52% +153 B 🔺
@sentry/browser (incl. Logs) 30.08 kB +0.46% +136 B 🔺
@sentry/browser (incl. Metrics & Logs) 30.74 kB +0.49% +149 B 🔺
@sentry/react 30.54 kB +0.32% +95 B 🔺
@sentry/react (incl. Tracing) 51.41 kB +0.26% +133 B 🔺
@sentry/vue 36.04 kB +0.36% +127 B 🔺
@sentry/vue (incl. Tracing) 51.46 kB +0.25% +124 B 🔺
@sentry/svelte 28.82 kB +0.4% +112 B 🔺
CDN Bundle 30.54 kB +0.39% +117 B 🔺
CDN Bundle (incl. Tracing) 49.72 kB +0.26% +125 B 🔺
CDN Bundle (incl. Logs, Metrics) 32.81 kB +0.47% +153 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) 51.69 kB +0.32% +160 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) 73.47 kB +0.22% +155 B 🔺
CDN Bundle (incl. Tracing, Replay) 87.28 kB +0.15% +126 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) 89.17 kB +0.18% +152 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) 93.21 kB +0.14% +122 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) 95.2 kB +0.18% +168 B 🔺
CDN Bundle - uncompressed 90.44 kB +0.35% +314 B 🔺
CDN Bundle (incl. Tracing) - uncompressed 148.16 kB +0.24% +350 B 🔺
CDN Bundle (incl. Logs, Metrics) - uncompressed 97.02 kB +0.52% +499 B 🔺
CDN Bundle (incl. Tracing, Logs, Metrics) - uncompressed 154.12 kB +0.35% +535 B 🔺
CDN Bundle (incl. Replay, Logs, Metrics) - uncompressed 226.27 kB +0.2% +450 B 🔺
CDN Bundle (incl. Tracing, Replay) - uncompressed 267.75 kB +0.12% +301 B 🔺
CDN Bundle (incl. Tracing, Replay, Logs, Metrics) - uncompressed 273.69 kB +0.18% +486 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback) - uncompressed 281.45 kB +0.11% +301 B 🔺
CDN Bundle (incl. Tracing, Replay, Feedback, Logs, Metrics) - uncompressed 287.39 kB +0.17% +486 B 🔺
@sentry/nextjs (client) 54.03 kB +0.27% +145 B 🔺
@sentry/sveltekit (client) 49.65 kB +0.28% +138 B 🔺
@sentry/core/server 41.09 kB +0.34% +139 B 🔺
@sentry/core/browser 13.55 kB +0.15% +20 B 🔺
@sentry/node 124.8 kB +0.13% +159 B 🔺
@sentry/node/import (ESM hook with diagnostics-channel injection) 81.51 kB - -
@sentry/node - without tracing 88.63 kB +0.18% +159 B 🔺
@sentry/node - without channel injection 104.09 kB +0.16% +161 B 🔺
@sentry/aws-serverless 97.01 kB +0.18% +169 B 🔺
@sentry/cloudflare (withSentry) - minified 201.89 kB +0.17% +336 B 🔺
@sentry/cloudflare (withSentry) 502.37 kB +0.2% +996 B 🔺

View base workflow run

Base automatically changed from ms/safe-callback-user-callbacks to develop September 3, 2026 09:16
@msonnb
msonnb force-pushed the ms/callback-error-drop-reason branch 2 times, most recently from dd74588 to 8f068cc Compare September 3, 2026 09:42
@msonnb

msonnb commented Sep 3, 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 8f068cc. Configure here.

@msonnb
msonnb marked this pull request as ready for review September 3, 2026 12:11
@msonnb
msonnb requested a review from a team as a code owner September 3, 2026 12:11
@msonnb
msonnb requested review from Lms24, isaacs and mydea and removed request for a team September 3, 2026 12:11
Comment thread packages/core/src/tracing/sampling.ts Outdated
samplingContext: SamplingContext,
sampleRand: number,
): [sampled: boolean, sampleRate?: number, localSampleRateWasApplied?: boolean] {
): SamplingDecision {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

m: this is API breaking, since sampleSpan is exported. I agree that the object is easier to read though . IIRC, we used the named tuple here for bundle size minimization but this is less readable than the refactor.

Breaking here isn't a big deal though, so we can also do it if the tuple no longer works. But if we do, let's add a note in the migration guide.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

oops, missed the public exported. was just for readability so i reverted to the tuple

Comment thread packages/core/src/eventProcessors.ts Outdated
() => processor({ ...event }, hint),
() => null,
() => {
throw CALLBACK_ERROR;

@Lms24 Lms24 Sep 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

m: throwing here and in client.ts made me a bit suspicious because we have to be really careful to also catch our throws. Looks like there's a case in replay where we also call prepareEvent which doesn't try/catch the call. I think this only concerns event processor throws though. This leads to us trying to re-send the replay because we assume a network error. Ultimately, we stop recording.

I think we have two options how to avoid this:

  1. we try/catch in Replay so that this doesn't happen
  2. we don't throw at all. Instead, we could directly record an dropped event in notifyEventProcessors and distinguish there.

Tbqh: I haven't thought this through end-to-end, so maybe 1 is easier. I don't see us reusing prepareEvent much in the foreseeable future. But happy to let you make the call (also feel free to come up with something else).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

so I went with option 2 for now, which means that notifyEventProcessors (which is also publicly exported from core) gains an extra (but optional and thus backwards-compatible) onDrop callback since it doesn't have a reference to the client currently. I guess we could also just pass the client directly, which would introduce more coupling, but probably save a few bytes.

something entirely else would be introducing some kind of result type like { ok: true; event } | { ok: false; error } but that feels a bit overkill and would change the function signatures entirely.

side note: I feel like Java-like checked exceptions would really help here 😅

msonnb and others added 2 commits September 4, 2026 10:53
…callbacks

Events, logs, metrics and root spans dropped because a user callback threw
were reported with the same outcome as a legitimate filter (`before_send`,
`event_processor`, `sample_rate`). A dedicated `callback_error` reason makes
them distinguishable.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@msonnb
msonnb force-pushed the ms/callback-error-drop-reason branch from 8f068cc to 9a3f5ed Compare September 4, 2026 08:53
@msonnb
msonnb requested a review from a team as a code owner September 4, 2026 08:53
@msonnb
msonnb requested review from Lms24 and removed request for a team September 4, 2026 08:53

@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.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 9a3f5ed. Configure here.

Comment thread packages/core/src/eventProcessors.ts
Treat callback failures as drops at the callback boundary. Event processors and beforeSend hooks now keep their normal Event | null return shape and report callback_error through dedicated callbacks instead of throwing or returning CALLBACK_ERROR.

prepareEvent records processor drops, while Client records beforeSend drops. This keeps the sentinel from escaping those pipelines and avoids duplicate client reports.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: OpenAI Codex <codex@openai.com>
@msonnb
msonnb force-pushed the ms/callback-error-drop-reason branch from 9a3f5ed to efbaddb Compare September 4, 2026 09:06
Comment on lines -56 to -57
// Taken from baseclient's `_processEvent` method, where this is handled for errors/transactions
client.recordDroppedEvent('event_processor', 'replay');

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

l: might be worth adding a comment here that this is handled within prepareEvent now

Lms24 commented Sep 4, 2026

Copy link
Copy Markdown
Member

thanks for making the changes!

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.

2 participants