Skip to content

feat(android): [Unhandled Sessions 3] Add internal non-terminating envelope capture - #5921

Draft
buenaflor wants to merge 8 commits into
feat/unhandled-sessions-cachefrom
feat/unhandled-sessions-internal-api
Draft

feat(android): [Unhandled Sessions 3] Add internal non-terminating envelope capture#5921
buenaflor wants to merge 8 commits into
feat/unhandled-sessions-cachefrom
feat/unhandled-sessions-internal-api

Conversation

@buenaflor

@buenaflor buenaflor commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

PR Stack (Unhandled Sessions)


📜 Description

Adds InternalSentrySdk.captureEnvelopeNonTerminating(byte[]) for hybrid runtimes where an unhandled exception does not terminate the process.

Unlike captureEnvelope(byte[], boolean), it does not treat handled=false as a crash. Instead it:

  • flags the current session and increments its error count,
  • keeps the session Ok with the same session id on the scope,
  • attaches no session item and starts no new session,
  • persists the session so the flag survives process death.

The session is finalized later by normal lifecycle (endSession, background, or previous-session recovery) as unhandled, unless a native crash escalates it to crashed. captureEnvelope(byte[], boolean) is unchanged.

Also in this PR:

  • Scope.IWithSession becomes public so InternalSentrySdk can mutate the session under the scope lock; it is the only consumer. Its @ApiStatus.Internal was dropped as inert — sentry.api tracks the type either way.
  • A shared scanEvents, replacing two loops that computed the same booleans by different routes, plus a shared readEnvelope.
  • catch (Throwable) narrowed to catch (Exception) so OutOfMemoryError and friends propagate instead of being swallowed.

💡 Motivation and Context

Flutter forwards handled=false events through the terminating hybrid capture path. That marks the session crashed and may start a replacement session even though the Flutter process keeps running, incorrectly lowering crash-free session rates.

💚 How did you test it?

New InternalSentrySdkTest coverage: the session staying Ok with the same id and the flag persisted to disk; endSession afterwards finalizing as unhandled; and a later hard crash finalizing the old session as crashed and starting a fresh Ok session. Existing captureEnvelope tests confirm that path is unchanged.

📝 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

Update the Flutter Android bridge to use captureEnvelopeNonTerminating for non-terminating unhandled events.

⚠️ Merge this PR using a merge commit (not squash). Only the collection branch is squash-merged into main.

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor
Messages
📖 Do not forget to update Sentry-docs with your feature once the pull request gets approved.

Generated by 🚫 dangerJS against 8d7ca5a

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@sentry

sentry Bot commented Aug 10, 2026

Copy link
Copy Markdown

📲 Install Builds

Android

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

⚙️ sentry-android Build Distribution Settings

@github-actions

github-actions Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Performance metrics 🚀

  Plain With Sentry Diff
Startup time 387.86 ms 457.88 ms 70.02 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
6b019b7 343.31 ms 417.23 ms 73.91 ms
d15471f 286.65 ms 314.68 ms 28.03 ms
d217708 409.83 ms 474.72 ms 64.89 ms
d500866 326.13 ms 378.70 ms 52.58 ms
fcec2f2 314.96 ms 373.66 ms 58.70 ms
d501a7e 314.55 ms 343.34 ms 28.79 ms
7414e9b 322.49 ms 378.88 ms 56.39 ms
fcec2f2 357.47 ms 447.32 ms 89.85 ms
a416a65 316.52 ms 359.67 ms 43.15 ms
983e0f0 350.64 ms 386.44 ms 35.79 ms

App size

Revision Plain With Sentry Diff
6b019b7 0 B 0 B 0 B
d15471f 1.58 MiB 2.13 MiB 559.54 KiB
d217708 1.58 MiB 2.10 MiB 532.97 KiB
d500866 0 B 0 B 0 B
fcec2f2 1.58 MiB 2.12 MiB 551.50 KiB
d501a7e 0 B 0 B 0 B
7414e9b 0 B 0 B 0 B
fcec2f2 1.58 MiB 2.12 MiB 551.50 KiB
a416a65 1.58 MiB 2.12 MiB 555.26 KiB
983e0f0 0 B 0 B 0 B

Previous results on branch: feat/unhandled-sessions-internal-api

Startup times

Revision Plain With Sentry Diff
f4f202f 315.94 ms 369.24 ms 53.30 ms
8014a1f 304.46 ms 376.38 ms 71.92 ms
ed254d0 331.02 ms 359.08 ms 28.06 ms
bc96797 321.86 ms 377.38 ms 55.52 ms
b696cfd 320.00 ms 358.66 ms 38.66 ms
075631e 355.90 ms 458.42 ms 102.52 ms

App size

Revision Plain With Sentry Diff
f4f202f 0 B 0 B 0 B
8014a1f 0 B 0 B 0 B
ed254d0 0 B 0 B 0 B
bc96797 0 B 0 B 0 B
b696cfd 0 B 0 B 0 B
075631e 0 B 0 B 0 B

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

6 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@buenaflor
buenaflor force-pushed the feat/unhandled-sessions-internal-api branch from 56ab999 to 1906ec6 Compare August 11, 2026 10:00
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

2 similar comments
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@buenaflor
buenaflor force-pushed the feat/unhandled-sessions-internal-api branch from 06f5823 to ae23921 Compare August 11, 2026 11:53
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@buenaflor
buenaflor force-pushed the feat/unhandled-sessions-internal-api branch from ae23921 to b2ff9d9 Compare August 11, 2026 11:54
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

@buenaflor
buenaflor force-pushed the feat/unhandled-sessions-internal-api branch from b2ff9d9 to 945602b Compare August 11, 2026 11:59
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

Hybrid runtimes such as Flutter report unhandled exceptions that do not
terminate the process. Routing those through captureEnvelope ends the
session as crashed and starts a replacement one, which understates
crash-free session rates. The new entry point keeps the session alive
with the same id, increments its error count, and marks it
pending-unhandled so it finalizes as unhandled at its natural end.

Co-authored-by: Cursor <cursoragent@cursor.com>
buenaflor and others added 6 commits August 11, 2026 14:06
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…thods

Both methods scanned the envelope's events to derive the same pair of
booleans, but wrote it differently - one via isCrashed(), the other via
getUnhandledException() != null, which is the same predicate. Extract a
single scanEvents returning NONE/ERRORED/UNHANDLED so the two agree by
construction and an unhandled-but-not-errored state is unrepresentable.

Co-authored-by: Cursor <cursoragent@cursor.com>
The annotation had no mechanical effect: apiValidation configures only
ignoredPackages/ignoredProjects and no nonPublicMarkers, so the type is
tracked in sentry.api either way. Regenerating the dump after removing
it produces no diff.

The interface still has to be public, since the lambda in
InternalSentrySdk.captureEnvelopeNonTerminating targets it from
io.sentry.android.core.

Co-authored-by: Cursor <cursoragent@cursor.com>
@buenaflor
buenaflor force-pushed the feat/unhandled-sessions-internal-api branch from 945602b to 91be174 Compare August 11, 2026 12:06
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

Both the method and the enum were plural nouns that read as if they
returned the envelope's events, when they return a single summary value.
That made "events != EnvelopeEvents.NONE" look like an emptiness check
rather than "nothing worth recording happened". EnvelopeEventState also
lines up with the Session.State vocabulary already used here.

Co-authored-by: Cursor <cursoragent@cursor.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚨 Detected changes in high risk code 🚨

High-risk code has higher potential to break the SDK and may be hard to test. To prevent severe bugs, apply the rollout process for releasing such changes and be extra careful when changing and reviewing these files:

  • sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java

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.

1 participant