Repository navigation
Conversation
… exits A fatal JS error was captured through InternalSentrySdk.captureEnvelope, which only queues the envelope on the single-threaded transport executor. React Native then rethrows the error as JavascriptException, an ignored exception type, so UncaughtExceptionHandlerIntegration skips the disk flush and the process dies with the envelope still in memory. In release builds most fatal JS errors never reached Sentry. When hardCrashed is set, read the envelope, end the current session as crashed and attach it (the same session handling as InternalSentrySdk.captureEnvelope), delete the current-session file, and write the envelope to options.getEnvelopeDiskCache() on the calling thread. The next launch sends the cached file, which matches the iOS store path. Without a disk cache, or when the envelope cannot be read, the previous queued path runs. When the store itself fails, the repackaged envelope is queued instead so only one copy exists. Fixes #6918
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
| if (!EnvelopeCache.getCurrentSessionFile(cacheDirPath).delete()) { | ||
| logger.log(SentryLevel.WARNING, "Failed to delete the current session file."); | ||
| } | ||
| } | ||
|
|
||
| final @NotNull SentryEnvelope repackaged = new SentryEnvelope(envelope.getHeader(), items); | ||
| if (!cache.storeEnvelope(repackaged, new Hint())) { | ||
| logger.log(SentryLevel.ERROR, "Failed to store the hard crash envelope, queueing it."); | ||
| scopes.captureEnvelope(repackaged); |
There was a problem hiding this comment.
Current session file is deleted even when hard-crash envelope persistence fails
The hard-crash path deletes the current-session file before storing the repackaged envelope. If cache.storeEnvelope fails, the envelope is only queued (or a thrown exception is caught by the outer handler), while the session file is already gone. Preserve the session file unless the envelope is successfully stored to disk, so the next launch can still report the session as abnormal.
Evidence
- The session is attached to
items, then its current-session file is deleted beforecache.storeEnvelopeis called. - When
storeEnvelopereturns false, the code queues the envelope throughscopes.captureEnvelope; the enclosing capture path can then exit while the process is about to terminate. - The existing store-failure test checks queue fallback but does not cover a session file surviving a failed store.
Identified by Warden · find-bugs · 638-86W
📢 Type of change
📜 Description
When
hardCrashedis true,RNSentryModuleImpl.captureEnvelopenow writes the envelope tooptions.getEnvelopeDiskCache()on the calling thread instead of queueing it on the transport executor. It applies the same session handling asInternalSentrySdk.captureEnvelope(end the session as crashed, attach it, delete the current-session file). The next launch sends the cached file, which matches the iOSstorepath. Without a disk cache the old queued path runs, and if the store fails the envelope is queued instead.💡 Motivation and Context
InternalSentrySdk.captureEnvelopeonly submits the envelope to the single-threaded transport executor. React Native then rethrows the fatal asJavascriptException, which is an ignored exception type, so the native SDK skips the disk flush and the process dies with the envelope still in memory. In release builds most fatal JS errors never reached Sentry.Fixes #6918
💚 How did you test it?
Added
RNSentryCaptureEnvelopeTestwith five cases (sync store, crashed session attached, fallback when the store fails, no disk cache, non-fatal path). Three of them fail onmainand all pass with this change. All Android unit tests andyarn lint:androidpass.📝 Checklist
sendDefaultPIIis enabled.