Skip to main content
Solved

Investigating a crash with NSError from sample project

  • January 27, 2026
  • 3 replies
  • 60 views

Chris-29
Forum|alt.badge.img+5

Hello! Could I please get some guidance on a code change for my app to address a crash that appears to be tied to some code from a RevenueCat sample project?

 

I have a shortcut that launches my iOS app and then navigates to a View. I realized that there is a crash scenario. If I initially run the shortcut from the Shortcuts app when the app wasn’t running it correctly launches the app and navigates to the View. However, if I then go back to the Shortcuts app and run the shortcut again the system correctly switches to the app but then the app crashes.

 

To investigate I ran the app in debug mode and was quite surprised to see where it was crashing. It was inside of my tip jar, which I haven’t changed the core logic for since I first developed my app in 2023.

 

I used the Magic Weather SwiftUI sample project as a basis for the consumable, in-app purchases in my tip jar.

 

Here’s the code that was causing the issue:

// from RC Magic Weather example
extension NSError: LocalizedError {
public var errorDescription: String? {
return self.localizedDescription
}
}

 

The problem was accessing self.localizedDescription and it gave the error Thread 38: EXC_BAD_ACCESS.

 

As the comment mentioned, I got this computed property from the Magic Weather SwiftUI sample app. I took a look at the current Github repository and it’s still there.

 

I asked Claude and it says that this is an infinite recursion issue because LocalizedError.errorDescription is what localizedDescription uses internally. So when a background thread uses NSError that error's description is accessed and hits the recursion.

 

That theory does seem to match the behavior I’m seeing. When the problem happens while debugging the app seems to hang for several seconds before crashing.

 

Initially Claude wanted me to completely remove the extension, but my tip jar won’t compile without it (got the generic “unable to type-check this expression...”).

 

Here’s the fix Claude suggested, which does stop the crash from occurring (and the shortcut performs as expected):

// Fixed: The original called self.localizedDescription which caused infinite recursion
// because LocalizedError.errorDescription is what localizedDescription uses internally.
// Instead, access the userInfo directly to avoid the cycle.
extension NSError: LocalizedError {
public var errorDescription: String? {
return userInfo[NSLocalizedDescriptionKey] as? String ?? domain + " \(code)"
}
}

 

I’m a little hesitant about modifying a global extension when my Objective-C knowledge is minimal.

 

How would you address this issue? 

Thank you for any help you can provide.

Best answer by Tarek

Hey Chris,

Thank you for reaching out. I’m Tarek, from the support team, and I’ll happily assist you.

While I wasn't able to reproduce it, it looks like the piece of code you shared can indeed cause some crashes in some cases.

One possible fix is to make a bespoke type that will conform to LocalizedError and bridge it with NSError.

You could remove the extension and introduce something like this instead:

struct PresentableNSError: LocalizedError {
let nsError: NSError

init(_ error: Error) {
self.nsError = error as NSError
}

var errorDescription: String? {
nsError.localizedDescription
}

var failureReason: String? {
nsError.localizedFailureReason ?? (nsError.userInfo[NSLocalizedFailureReasonErrorKey] as? String)
}

var recoverySuggestion: String? {
nsError.localizedRecoverySuggestion ?? (nsError.userInfo[NSLocalizedRecoverySuggestionErrorKey] as? String)
}

var helpAnchor: String? {
nsError.helpAnchor ?? (nsError.userInfo[NSHelpAnchorErrorKey] as? String)
}
}

 

Don't forget to set the affected error instance variables types as PresentableNSError instead of NSError in your code.

 

I have made a PR to fix that in our sample code as well.

 

Since I wasn't able to reproduce (it depends on many factors), could you please confirm if this fix is working?

 

Best regards, 

 

Tarek, from RevenueCat.

3 replies

Tarek
RevenueCat Staff
Forum|alt.badge.img+3
  • RevenueCat Staff
  • Answer
  • January 29, 2026

Hey Chris,

Thank you for reaching out. I’m Tarek, from the support team, and I’ll happily assist you.

While I wasn't able to reproduce it, it looks like the piece of code you shared can indeed cause some crashes in some cases.

One possible fix is to make a bespoke type that will conform to LocalizedError and bridge it with NSError.

You could remove the extension and introduce something like this instead:

struct PresentableNSError: LocalizedError {
let nsError: NSError

init(_ error: Error) {
self.nsError = error as NSError
}

var errorDescription: String? {
nsError.localizedDescription
}

var failureReason: String? {
nsError.localizedFailureReason ?? (nsError.userInfo[NSLocalizedFailureReasonErrorKey] as? String)
}

var recoverySuggestion: String? {
nsError.localizedRecoverySuggestion ?? (nsError.userInfo[NSLocalizedRecoverySuggestionErrorKey] as? String)
}

var helpAnchor: String? {
nsError.helpAnchor ?? (nsError.userInfo[NSHelpAnchorErrorKey] as? String)
}
}

 

Don't forget to set the affected error instance variables types as PresentableNSError instead of NSError in your code.

 

I have made a PR to fix that in our sample code as well.

 

Since I wasn't able to reproduce (it depends on many factors), could you please confirm if this fix is working?

 

Best regards, 

 

Tarek, from RevenueCat.


Chris-29
Forum|alt.badge.img+5
  • Author
  • Dedicated Member
  • January 29, 2026

 

Since I wasn't able to reproduce (it depends on many factors), could you please confirm if this fix is working?

 

Hi Tarek,

 

Thank you for such a quick, detailed response. I mimicked the approach that you took in your PR and can verify that your fix worked.  The crash scenario is now gone.

 

Thank you for the help!


Tarek
RevenueCat Staff
Forum|alt.badge.img+3
  • RevenueCat Staff
  • January 30, 2026

Hey Chris,

 

I'm very happy that this fixed you issue! I've submitted the PR for a quick fix in the sample code.

Thank you for reporting this!

 

Best regards,