Skip to content

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

Open
buenaflor wants to merge 27 commits into
feat/unhandled-sessions-cachefrom
feat/unhandled-sessions-internal-api
Open

feat(android): [Unhandled Sessions 3] Add internal non-terminating envelope capture#5921
buenaflor wants to merge 27 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 terminal status takes over first, such as crashed for a native crash or abnormal for an ANR. 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. It carries @ApiStatus.Internal like IWithTransaction and IWithPropagationContext, so it is not supported API despite being public.
  • A shared eventStateOf returning EnvelopeEventState, replacing two loops that computed the same booleans by different routes, plus a shared readEnvelope.
  • The code added here catches Exception rather than Throwable, so OutOfMemoryError and friends propagate instead of being swallowed. The existing captureEnvelope keeps its catch (Throwable).

💡 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 960c618

@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.53.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 326.08 ms 364.78 ms 38.70 ms
Size 0 B 0 B 0 B

Baseline results on branch: main

Startup times

Revision Plain With Sentry Diff
bb0ff41 344.70 ms 413.82 ms 69.12 ms
a979f23 333.24 ms 391.02 ms 57.78 ms
05aa61d 326.06 ms 385.46 ms 59.40 ms
fc5ccaf 270.49 ms 363.90 ms 93.41 ms
9ea89e8 308.06 ms 358.16 ms 50.10 ms
6b019b7 403.90 ms 546.09 ms 142.19 ms
ad8da22 314.52 ms 352.47 ms 37.95 ms
96eeafa 361.43 ms 455.07 ms 93.63 ms
ed33deb 343.30 ms 362.41 ms 19.10 ms
ee747ae 554.98 ms 611.50 ms 56.52 ms

App size

Revision Plain With Sentry Diff
bb0ff41 0 B 0 B 0 B
a979f23 0 B 0 B 0 B
05aa61d 0 B 0 B 0 B
fc5ccaf 1.58 MiB 2.13 MiB 557.54 KiB
9ea89e8 1.58 MiB 2.28 MiB 716.23 KiB
6b019b7 0 B 0 B 0 B
ad8da22 1.58 MiB 2.29 MiB 719.83 KiB
96eeafa 1.58 MiB 2.19 MiB 620.21 KiB
ed33deb 1.58 MiB 2.13 MiB 559.52 KiB
ee747ae 1.58 MiB 2.10 MiB 530.95 KiB

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

Startup times

Revision Plain With Sentry Diff
ed254d0 331.02 ms 359.08 ms 28.06 ms
8014a1f 304.46 ms 376.38 ms 71.92 ms
bc96797 321.86 ms 377.38 ms 55.52 ms
e854020 317.72 ms 358.13 ms 40.40 ms
0ac26dc 390.71 ms 438.00 ms 47.29 ms
4f9af8d 329.51 ms 342.60 ms 13.09 ms
f4f202f 315.94 ms 369.24 ms 53.30 ms
211ab30 314.79 ms 389.47 ms 74.68 ms
0650636 387.86 ms 457.88 ms 70.02 ms
b696cfd 320.00 ms 358.66 ms 38.66 ms

App size

Revision Plain With Sentry Diff
ed254d0 0 B 0 B 0 B
8014a1f 0 B 0 B 0 B
bc96797 0 B 0 B 0 B
e854020 0 B 0 B 0 B
0ac26dc 0 B 0 B 0 B
4f9af8d 0 B 0 B 0 B
f4f202f 0 B 0 B 0 B
211ab30 0 B 0 B 0 B
0650636 0 B 0 B 0 B
b696cfd 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

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

Comment thread sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java Outdated
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

@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

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

@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

captureEnvelopeNonTerminating called persistCurrentSession from inside the
withSession callback, so synchronous session-file I/O ran while holding the
scope sessionLock, on the platform thread for Flutter. Mutate under the lock
and write the clone withSession returns, the way SentryClient.updateSessionData
uses its snapshot.

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

@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 da288f8. Configure here.

Comment thread sentry-android-core/src/main/java/io/sentry/android/core/InternalSentrySdk.java Outdated
@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

Three reviewers in a row read the persist as accidentally holding the scope
lock, so say why it is deliberate. Also name abnormal alongside crashed as a
terminal status that wins over the unhandled marker, following the Session
javadoc.

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

@runningcode runningcode left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This looks good aside from the exception handling!

final @NotNull SentryOptions options, final @NotNull byte[] envelopeData) {
try (final InputStream envelopeInputStream = new ByteArrayInputStream(envelopeData)) {
return options.getEnvelopeReader().read(envelopeInputStream);
} catch (Exception e) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should only catch the exceptions expect to throw here. Looks like we expect IOException and IllegalArgumentException ?

final SentryEnvelope repackagedEnvelope =
new SentryEnvelope(envelope.getHeader(), envelopeItems);
return scopes.captureEnvelope(repackagedEnvelope);
} catch (Throwable t) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

since we arent doing disk I/O inside the try/catch, why do we need this? which parts can throw Exceptions ?

}

return scopes.captureEnvelope(envelope);
} catch (Exception e) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We should try to capture the narrowest exception possible as written in the AGENTS.md file now. Might need to rebase to get this update.

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.

3 participants