fix(react-native): skip duplicate native report for fatal unhandled JS errors on iOS - #380
Merged
Merged
Conversation
KishanPRao
marked this pull request as ready for review
July 30, 2026 17:13
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.
Summary
On iOS a fatal unhandled JS error was reported twice (a JS "Unhandled exception" plus a redundant native "Crash"); this drops the native duplicate while keeping the JS report.
Adds a jest test for the marker, and makes the example's "Throw an unhandled error" button a real fatal.
Changes
UnhandledExceptionHandler.ts: on a fatal error, callCrashReporter.markFatalError()before chaining the previous global handler.CrashReporter.ts: add an optional-chained staticmarkFatalError(), a no-op where the native binding is absent (Android).BacktraceReactNative.mm: exportmarkFatalErroras a blocking-synchronous method so the flag is set beforeRCTFatal.BacktraceCrashReporter.h: declaremarkJsFatalError.BacktraceCrashReporter.mm: stash ajsFatalflag in the crash's PLCrashReportercustomData, purge that pending report on next launch, self-clear the flag after 2s.unhandledExceptionHandlerTests.spec.ts: covermarkFatalErrorfiring on a fatal error and not on a non-fatal one.actions.ts: make "Throw an unhandled error" a real fatal via a deferred throw instead of an async rejection.Note
The 2s self-clear calls
saveReportDataon the main queue, which can race the module-thread attribute setters; harmless (a stale attribute at worst), can be serialized in a follow-up.ref: BT-7403