fix: exceptions thrown from BeforeBreadcrumb, log filters and BeforeScreenshotCapture no longer reach the application - #5606
Merged
Conversation
…creenshotCapture no longer reach the application Completes the callback-isolation work item from #5535 that #5545 started for TracesSampler. Each callback now runs inside a recovery boundary that logs an error naming the callback and applies the spec's fallback: - BeforeBreadcrumb (Scope.AddBreadcrumb, Android JNI, Cocoa) drops the breadcrumb - ILogEntryFilter.Filter treats a failing filter as "did not filter" - SetBeforeScreenshotCapture skips the screenshot and keeps the event Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 tasks
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #5606 +/- ##
==========================================
+ Coverage 74.84% 74.91% +0.07%
==========================================
Files 515 515
Lines 18962 18966 +4
Branches 3694 3696 +2
==========================================
+ Hits 14192 14209 +17
+ Misses 3892 3877 -15
- Partials 878 880 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
jamescrosswell
commented
Sep 22, 2026
…ndroid device tests Addresses review feedback on #5606: distinguish native callback failures from managed ones in the diagnostic log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
11 tasks
jamescrosswell
marked this pull request as ready for review
September 23, 2026 01:14
jamescrosswell
added this pull request to stack #5618
September 23, 2026 08:04
ric-oliv
reviewed
Sep 23, 2026
ric-oliv
approved these changes
Sep 23, 2026
ric-oliv
left a comment
Member
There was a problem hiding this comment.
Looks good! Just one comment about the naming.
ric-oliv
reviewed
Sep 23, 2026
ric-oliv
self-requested a review
September 23, 2026 11:20
…ng it through Review feedback on #5606. Failing open meant a filter written to exclude entries would, once broken, start sending them. Before this PR the exception reached the app and nothing was sent, so dropping keeps that outcome while removing the crash, and matches the filter rule applied to BeforeSend in #5610. Also aligns the internal screenshot callback names with the public SetBeforeScreenshotCapture, and fixes a doc sample naming a method that no longer exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
ShouldCaptureEvent and ShouldAddBreadcrumb each ran the whole filter chain, so a user filter was invoked twice for every entry that cleared both thresholds — and, since the previous commit, logged its failure twice. The two predicates now test only their level threshold, and the shared guard runs once in Log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
jamescrosswell
removed this pull request from stack #5618
September 27, 2026 22:01
jamescrosswell
added this pull request to stack #5628
September 27, 2026 22:01
jamescrosswell
removed this pull request from stack #5628
September 27, 2026 22:01
5 tasks
ric-oliv
approved these changes
Sep 28, 2026
jamescrosswell
added a commit
that referenced
this pull request
Sep 28, 2026
…nted in client reports (#5607) * fix: exceptions thrown from BeforeBreadcrumb, log filters and BeforeScreenshotCapture no longer reach the application Completes the callback-isolation work item from #5535 that #5545 started for TracesSampler. Each callback now runs inside a recovery boundary that logs an error naming the callback and applies the spec's fallback: - BeforeBreadcrumb (Scope.AddBreadcrumb, Android JNI, Cocoa) drops the breadcrumb - ILogEntryFilter.Filter treats a failing filter as "did not filter" - SetBeforeScreenshotCapture skips the screenshot and keeps the event Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ref: name the platform in native BeforeBreadcrumb failure logs, add Android device tests Addresses review feedback on #5606: distinguish native callback failures from managed ones in the diagnostic log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: record client reports for items dropped by user callbacks Work item 2 of #5535. Items lost to a user callback — whether it returned null or threw — were disappearing without a client report, and a throwing event or transaction processor skipped the report entirely by unwinding to the Hub catch-all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: record client reports for logs and metrics dropped by validation A log whose template doesn't match its arguments, and a metric with an unsupported value type or an empty name, were dropped with a diagnostic log and no client report. Records the spec's `invalid` reason, which the SDK did not previously carry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: log when BeforeSendLog or BeforeSendMetric drops an item Every other deliberate drop by a user callback logs at info level naming the callback; logs and metrics were the exception. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: a throwing log entry filter now drops the entry instead of letting it through Review feedback on #5606. Failing open meant a filter written to exclude entries would, once broken, start sending them. Before this PR the exception reached the app and nothing was sent, so dropping keeps that outcome while removing the crash, and matches the filter rule applied to BeforeSend in #5610. Also aligns the internal screenshot callback names with the public SetBeforeScreenshotCapture, and fixes a doc sample naming a method that no longer exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ref: evaluate log entry filters once per log call instead of twice ShouldCaptureEvent and ShouldAddBreadcrumb each ran the whole filter chain, so a user filter was invoked twice for every entry that cleared both thresholds — and, since the previous commit, logged its failure twice. The two predicates now test only their level threshold, and the shared guard runs once in Log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: report callback failures with the callback_error discard reason Follows the hooks spec revision in getsentry/sentry-docs#19189 (b53c3009): a throwing callback must be distinguishable from an explicit drop, so every item a failure drops is recorded as callback_error with the item's category. Null returns keep their existing reasons. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: rebuild the pull request merge ref GitHub stopped rebuilding refs/pull/5607/merge, so no pull_request workflow could be created and the PR reported a conflict that git shows does not exist. A new head commit forces the ref to be recomputed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
jamescrosswell
added a commit
that referenced
this pull request
Sep 29, 2026
…e item instead of sending it (#5610) * fix: exceptions thrown from BeforeBreadcrumb, log filters and BeforeScreenshotCapture no longer reach the application Completes the callback-isolation work item from #5535 that #5545 started for TracesSampler. Each callback now runs inside a recovery boundary that logs an error naming the callback and applies the spec's fallback: - BeforeBreadcrumb (Scope.AddBreadcrumb, Android JNI, Cocoa) drops the breadcrumb - ILogEntryFilter.Filter treats a failing filter as "did not filter" - SetBeforeScreenshotCapture skips the screenshot and keeps the event Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ref: name the platform in native BeforeBreadcrumb failure logs, add Android device tests Addresses review feedback on #5606: distinguish native callback failures from managed ones in the diagnostic log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: record client reports for items dropped by user callbacks Work item 2 of #5535. Items lost to a user callback — whether it returned null or threw — were disappearing without a client report, and a throwing event or transaction processor skipped the report entirely by unwinding to the Hub catch-all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: an exception in BeforeSend or BeforeSendTransaction now drops the item Work item 3 of #5535. Both callbacks previously demystified the exception, stapled its message and stack trace onto the item as a breadcrumb, and sent the item anyway. The spec says a callback failure MUST NOT be attached to the item, and that filters drop — a callback that threw part-way may not have applied the redaction the user wrote it to apply, so the partially-scrubbed item plus the exception detail were both reaching Sentry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: record client reports for logs and metrics dropped by validation A log whose template doesn't match its arguments, and a metric with an unsupported value type or an empty name, were dropped with a diagnostic log and no client report. Records the spec's `invalid` reason, which the SDK did not previously carry. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: log when BeforeSendLog or BeforeSendMetric drops an item Every other deliberate drop by a user callback logs at info level naming the callback; logs and metrics were the exception. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: a throwing log entry filter now drops the entry instead of letting it through Review feedback on #5606. Failing open meant a filter written to exclude entries would, once broken, start sending them. Before this PR the exception reached the app and nothing was sent, so dropping keeps that outcome while removing the crash, and matches the filter rule applied to BeforeSend in #5610. Also aligns the internal screenshot callback names with the public SetBeforeScreenshotCapture, and fixes a doc sample naming a method that no longer exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * ref: evaluate log entry filters once per log call instead of twice ShouldCaptureEvent and ShouldAddBreadcrumb each ran the whole filter chain, so a user filter was invoked twice for every entry that cleared both thresholds — and, since the previous commit, logged its failure twice. The two predicates now test only their level threshold, and the shared guard runs once in Log. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: a throwing BeforeSend on the Android bridge no longer sends the unscrubbed native event The JNI bridge wrapped its whole body in a catch that returns the original Java event, so a scrubber that threw part-way sent the completely unredacted native event. That catch was added for serialization safety, so the guard goes around the user callback inside BeforeSendWrapper instead: it returns null, which the Java SDK turns into a drop and accounts for in its own client report, and Execute's catch keeps failing open only for serialization. Also covers the Cocoa native-crash path, where a throwing callback now drops the event and previously had no test at all. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * test: move the Cocoa BeforeSend tests in with the existing ProcessOnBeforeSend family Sentry.Tests.SentrySdkTests already has six ProcessOnBeforeSend tests inside an #if __IOS__ block. A second SentrySdkTests class under Platforms/iOS was a confusing duplicate name in a parallel namespace. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: report callback failures with the callback_error discard reason Follows the hooks spec revision in getsentry/sentry-docs#19189 (b53c3009): a throwing callback must be distinguishable from an explicit drop, so every item a failure drops is recorded as callback_error with the item's category. Null returns keep their existing reasons. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fix: report BeforeSend and BeforeSendTransaction failures as callback_error Follows the hooks spec revision in getsentry/sentry-docs#19189 (b53c3009). BeforeSendTransaction now records its own discard so a throw is distinguishable from a null return, which the shared caller could not tell apart. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * chore: rebuild the pull request merge ref GitHub stopped rebuilding refs/pull/5607/merge, so no pull_request workflow could be created and the PR reported a conflict that git shows does not exist. A new head commit forces the ref to be recomputed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
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
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Finishes work item 1 ("isolate the callbacks that can reach the host app") of #5535. #5545 already covered
TracesSampleron all three paths; this covers the remaining five boxes.Each callback now runs inside a recovery boundary that logs an error naming the callback and applies the fallback the Callback Error Isolation spec asks for. Nothing changes for anyone whose callbacks don't throw, and there's no public API change.
BeforeBreadcrumbScope.AddBreadcrumbBeforeBreadcrumbPlatforms/Android/Callbacks/BeforeBreadcrumbCallbacknull— drop the breadcrumbBeforeBreadcrumbPlatforms/Cocoa/SentrySdknull— drop the breadcrumbILogEntryFilter.FilterSentry.Extensions.Logging/SentryLoggerSetBeforeScreenshotCaptureSentry.Maui/Internal/SentryMauiScreenshotProcessorNotes for review:
Scope.AddBreadcrumbwas only accidentally isolated before:HubExtensions.AddBreadcrumbhappens to route throughHub.ConfigureScope's catch-all, butScope.AddBreadcrumbis public and a direct call was unprotected — and the catch-all's"Failure to ConfigureScope"doesn't tell anyone their breadcrumb callback is broken.ILogEntryFilterdrops the entry, rather than letting it through as "did not filter". That was review feedback, and the argument for it is that before this PR the exception reached the app and nothing was sent — so failing open would have changed the data behaviour on top of fixing the crash, in the direction that leaks. A filter written to exclude entries would, once broken, start sending them. Dropping keeps the old outcome and only removes the crash. It also matches the spec rationale for filters and what fix: an exception in BeforeSend or BeforeSendTransaction now drops the item instead of sending it #5610 does forBeforeSend. (Conform to the callback error isolation spec (wrap all user callbacks) #5535 proposed "treat as did not filter";ILogEntryFilterisn't in the spec matrix, so that line was a judgement call rather than anything normative, and it was the wrong one.)ShouldCaptureEventandShouldAddBreadcrumbeach ran the whole chain, so user filter code was invoked twice for any entry clearing both thresholds — and, once failures are logged, logged twice. Their shared tail is now a single early return inLog, leaving the two predicates to test only their own level threshold. Never zero:IsEnabledalready guarantees at least one threshold is met, so anything reaching that line evaluated the chain at least once before.SetBeforeScreenshotCapture(BeforeCaptureInternal→BeforeScreenshotCaptureInternal), and a doc sample calling a non-existentSetBeforeCaptureis fixed. The public parameter is still namedbeforeCapture— parameter names are in the API approval snapshots and renaming breaks named arguments, so that's left alone.SetBeforeScreenshotCapturepreviously unwound to theHub.CaptureEventcatch-all and dropped the whole event, losing the error the user was trying to report.BeforeBreadcrumbhas no report in the spec matrix, andILogEntryFilter/SetBeforeScreenshotCapturearen't in it. Work items 2 (fix: telemetry dropped by user callbacks and by validation is now counted in client reports #5607) and 3 (fix: an exception in BeforeSend or BeforeSendTransaction now drops the item instead of sending it #5610) of Conform to the callback error isolation spec (wrap all user callbacks) #5535 cover the reports and theBeforeSendalignment, so this doesn't close the issue.BeforeBreadcrumbCallbackTests, run on API 34 and 36 across net9.0/net10.0). The Cocoa bridge isn't: itsBeforeBreadcrumbis a lambda assigned inline inInitSentryCocoaSdkwith no seam to invoke without initialising the native SDK. Extracting it would make it testable the same way — worth doing, but as its own change.🤖 Generated with Claude Code