Skip to content

Production-only crash due to Reanimated import #3767

@mozzius

Description

@mozzius

Description

Alternative title: The Mystery of the Unused Component

First of all, I want to apologise for this this not being an actionable bug report. I am writing this more as an effort to document what happened, in the off chance it might help others. I cannot figure out a minimal repro because the circumstances that cause this to happen are very bizarre.

With that said, after upgrading Expo to SDK 54 we started getting rare crash in the Testflight build of our app. The instances are correlated with toasts being shown - we use https://github.com/gunnartorfis/sonner-native, which uses RNGH under the hood. Specifically, each toast has a gesture detector to handle swipe-to-dismiss.

While most crashes were very infrequent and rare, we eventually found a menu action (direct message "copy message text" button) that crashed consistently. I still don't know why this one is special. Regardless, it was a lead. However, it was not reproducible locally. I was eventually able to get the relevant error message out of the Console.

Image

The crash was due to a Reanimated debug component that we don't use. I exported the JS bundle and grepped it to confirm we don't use it anywhere, and this was indeed the case. We don't use PerformanceMonitor anywhere, and neither do any of our dependencies. In fact, if I then added PerformanceMonitor to the app, it stopped crashing. I also found I was able to reproduce by running the dev server with the --no-dev flag.

I eventually was able to get a more complete stack trace out of Sentry, and it pointed to the GestureDetector in the toasts. So I believe what is happening here is:

  1. A GestureDetector is created
  2. This creates an Animated.View via Wrap here
  3. Because Reanimated is an optional/dynamic import via a l, it gets re-imported here
  4. This causes PerformanceMonitor.tsx in Reanimated to get re-run
  5. PerformanceMonitor.tsx calls addWhitelistedNativeProps({ text: true }) at the top level, which throws
    • my guess is addWhitelistedNativeProps is non-idemponent?
  6. The PerformanceMonitor component therefore never gets exported from the file, which causes the app to crash

At this point I just decided to patch delete PerformanceMonitor.tsx, which fixed the crash, so unfortunately I was not able to get all the way to the bottom of this mystery. I hope this is helpful for someone? Or someone could point to what I'm missing?

The next step will be to strip the Bluesky app down until we can identify a minimal repro, but unfortunately I simply don't have the capacity do this. Also, addWhitelistedNativeProps was removed in Reanimated v4, so it won't even be an issue in the future once we're able to upgrade.

Steps to reproduce

  1. Start app with --no-dev
  2. Add sonner-native to your app
  3. ???
  4. Trigger a toast
  5. Observe crash

A link to a Gist, an Expo Snack or a link to a repository based on this template that reproduces the bug.

https://github.com/bluesky-social/social-app/tree/d4d5d6d8b9ad09e99a855d006c9bfbdf7cdc5561

Gesture Handler version

2.28.0

React Native version

0.81

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Using Expo Prebuild or an Expo development build

Architecture

Old Architecture (Paper)

Build type

Release mode

Device

Real device

Device model

iPhone 14, iPhone 17 simulator

Acknowledgements

Yes

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions