Skip to content

fix(core): Exclude reusable errors from deduplication - #6465

Draft
adinauer wants to merge 8 commits into
9.x.xfrom
fix/netty-read-timeout-deduplication
Draft

adinauer wants to merge 8 commits into
9.x.xfrom
fix/netty-read-timeout-deduplication

Conversation

@adinauer

@adinauer adinauer commented Nov 5, 2026

Copy link
Copy Markdown
Member

📜 Description

Adds ignoredErrorsForDeduplication to let exception types bypass throwable-based event deduplication by fully qualified class name or full regular expression.

io.netty.handler.timeout.ReadTimeoutException is excluded by default. Netty reuses ReadTimeoutException.INSTANCE for independent timeout occurrences, so storing that singleton in the SDK-lifetime deduplication map previously caused later timeouts to be discarded indefinitely.

Configuration semantics:

  • setIgnoredErrorsForDeduplication replaces the built-in list; null or an empty list removes all exclusions.
  • addIgnoredErrorForDeduplication extends the current list and therefore preserves the default entry.
  • Exact entries match the fully qualified runtime class name. Regular expressions use full-string matching and do not automatically include subclasses.
  • This change exposes programmatic configuration only.

Excluded types are neither checked against nor inserted into the deduplication map. This restores independent occurrences, but also means that multiple integrations capturing the same excluded exception may each send an event. For N occurrences captured through K integrations, volume can reach N × K, which can increase event quota and customer cost during timeout bursts.

💡 Motivation and Context

Netty holds a static reference to ReadTimeoutException.INSTANCE. Because the SDK deduplication processor uses throwable keys in a weak map, the static singleton never becomes collectible and its first capture can suppress unrelated later timeouts for the lifetime of the SDK client.

The configurable exclusion keeps deduplication enabled for other exception types while allowing known reusable exceptions to fail open.

Fixes #6365
Refs JAVA-794

💚 How did you test it?

  • ./gradlew :sentry:test --tests io.sentry.DuplicateEventDetectionEventProcessorTest --tests io.sentry.SentryOptionsTest
  • ./gradlew spotlessApply apiDump
  • git diff --check

📝 Checklist

  • I added GH Issue ID & Linear ID
  • I added tests to verify the changes.
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled.
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • Review from the native team if needed.
  • No breaking change or entry added to the changelog.
  • No breaking change for hybrid SDKs or communicated to hybrid SDKs.
  • Public API changes reviewed by another Mobile SDK team member or implemented according to the develop docs spec.

🔮 Next steps

None.

Allow exception class names and patterns to bypass throwable-based event deduplication. Exclude Netty ReadTimeoutException by default so its static singleton does not suppress independent timeout occurrences for the SDK lifetime.

Fixes #6365
@linear-code

linear-code Bot commented Nov 5, 2026

Copy link
Copy Markdown

JAVA-794

@sentry

sentry Bot commented Nov 5, 2026 •

Copy link
Copy Markdown

📲 Install Builds

Android

🔗 App Name App ID Version Configuration
SDK Size io.sentry.tests.size 8.63.0 (1) release

⚙️ sentry-android Build Distribution Settings

@markushi markushi left a comment

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.

LGTM!

*
* @return the list of exception class names excluded from event deduplication
*/
public @Nullable List<FilterString> getIgnoredErrorsForDeduplication() {

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.

I'm wondering if we should mark those APIs as internal for now, unless someone requests access.

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.

The idea was to give everyone a tool to exclude their own singleton exceptions, so I think it should be public.

Allow deduplication exclusions to be configured through external properties,
Android manifest metadata, and Spring Boot binding.

Preserve built-in defaults when unset and replace them when explicitly
configured, including empty lists.

Refs GH-6365

Co-Authored-By: Claude <noreply@anthropic.com>
@adinauer
adinauer force-pushed the fix/netty-read-timeout-deduplication branch from e995cdd to 4e5a867 Compare November 6, 2026 11:00
adinauer and others added 5 commits November 6, 2026 12:08
Return deduplication exclusions as strings while retaining compiled filters through an internal getter. This keeps the public getter and setter symmetric and prevents callers from mutating internal state.

Refs #6365
Co-Authored-By: Claude <noreply@anthropic.com>
Resolve conflicts after the symmetric ignored-filter getter changes landed on the target branch. Preserve the string-based getter API and the new deduplication configuration.

Co-Authored-By: Claude <noreply@anthropic.com>
Netty reuses WriteTimeoutException.INSTANCE across independent timeout
occurrences. Exclude it by default alongside ReadTimeoutException so later
write timeout events are not suppressed for the SDK lifetime.

Refs #6365
Co-Authored-By: Claude <noreply@anthropic.com>
Return ignored top-level exceptions before checking their causes so configured
exclusions consistently preserve the event.

Refs #6365
Co-Authored-By: Claude <noreply@anthropic.com>
Treat ignored exceptions as cause-chain boundaries so deeper causes do not
discard an event while non-ignored wrappers remain deduplicatable.

Refs #6365
Co-Authored-By: Claude <noreply@anthropic.com>

This branch has not been deployed

No deployments
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