Skip to content

SentryCrash.doctorReport crashes on launch with NSInvalidArgumentException (objectForKeyedSubscript: sent to __NSArrayM), causing a permanent crash-loop #7888

Description

@vtoupet

Platform

iOS

Environment

Production

Installed

CocoaPods (transitively via @sentry/react-native 8.3.0 → RNSentry pod → Sentry pod 9.6.0)

Other Error Monitoring Solution

No

Version

sentry-cocoa 9.6.0 (Sentry pod, locked by @sentry/react-native@8.3.0)

Xcode Version

26.4.1 (build 17E202)

Did it work on previous versions?

Not investigated for this report — the affected user is on a build that has shipped with sentry-cocoa 9.6.0 since release.

Steps to Reproduce

I cannot reproduce this on demand — it has hit one user, but consistently. Observed externally:

  1. User launches the app (production build, App Store distribution).
  2. SentrySDK.start runs synchronously during app startup.
  3. As part of installIntegrations, SentryCrashIntegration calls SentryCrash.sendAllReportsWithCompletion:, which iterates over previously persisted crash reports on disk.
  4. While processing one of those reports, -[SentryCrash doctorReport:] throws NSInvalidArgumentException: -[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance 0x....
  5. The exception is unhandled (mechanism: nsexception, handled: no, level: fatal) and crashes the app before any application code runs.
  6. On the next launch the same on-disk report is replayed → crash repeats. The user is in a permanent crash-loop until they reinstall the app (which clears the on-disk Sentry crash store).

Frequency: 5 fatal events over ~17 hours from the same identifierForVendor, single user, no other users affected on the same build.
App context at the time of the crash: in_foreground: true, is_active: false (i.e. during launch, before the app has become active).

Expected Result

-[SentryCrash doctorReport:] should defensively handle a stored crash report whose JSON shape doesn't match expectations — for example, a value the doctor expects to be an NSDictionary that is actually an NSArray. On a shape mismatch the SDK should either skip and delete the malformed report, or produce a best-effort report, but it must not throw an unhandled NSException from inside SentrySDK.start.

In particular: the SDK starting up should never be able to crash-loop the host app on subsequent launches based on data the SDK itself wrote to disk on a previous run.

Actual Result

NSInvalidArgumentException
-[__NSArrayM objectForKeyedSubscript:]: unrecognized selector sent to instance 0x112b8c000

Stack (top frames trimmed for the throw, bottom frames trimmed at UIApplicationMain):

objc_exception_throw
-[NSObject(NSObject) doesNotRecognizeSelector:]
___forwarding___
__forwarding_prep_0___
-[SentryCrash doctorReport:]                               ← crash site
-[SentryCrash reportWithIntID:]
-[SentryCrash allReports]
-[SentryCrash sendAllReportsWithCompletion:]
SentryCrashSwift.sendAllReports
-[SentryCrashInstallation sendAllReportsWithCompletion:]
SentryCrashIntegration.init
SentrySwiftIntegrationInstaller.install
+[SentrySDKInternal installIntegrations]
__38+[SentrySDKInternal startWithOptions:]_block_invoke
-[_SentryDispatchQueueWrapperInternal dispatchAsyncOnMainQueueIfNotMainThread:]
SentryDispatchQueueWrapper.dispatchAsyncOnMainQueueIfNotMainThread
+[SentrySDKInternal startWithOptions:]
SentrySDK.start
+[RNSentryStart startWithOptions:]
+[RNSentryStart startWithOptions:error:]
-[RNSentry initNativeSdk:resolve:rejecter:]
... (UIApplicationMain)

What I've ruled out

Asks

  1. Is this a known bug already fixed somewhere between 9.6.0 and HEAD that I missed?
  2. If not, is there a safe SentryOptions knob — or, in a future release, a documented procedure — for users in this state to recover without reinstalling the app?
  3. If neither, would a defensive isKindOfClass: check inside doctorReport (with "delete-and-skip" on shape mismatch) be acceptable as a PR?

I'm happy to share the full Sentry event JSON privately if it would help diagnose which key/field in the stored report is the array-vs-dict that the doctor is choking on.

Are you willing to submit a PR?

Yes, with guidance on which file owns the doctor-report parsing and what the expected shape is supposed to be.

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions