software-mansion / react-native-reanimated

React Native's Animated library reimplemented
https://docs.swmansion.com/react-native-reanimated/
MIT License
8.87k stars 1.3k forks source link

Crashing in Production Mode When Trying to Open the Drawer #5067

Closed aslihanturkdonmez closed 1 year ago

aslihanturkdonmez commented 1 year ago

Description

I'm experiencing a crash when attempting to open the drawer in a React Native project using Reanimated v3. Debug mode is functioning correctly, but in production, the app crashes on both Android and iOS. I've created a new React Native project (0.72.4) and installed the necessary navigation and drawer packages.

reanimated_crash

Steps to reproduce

I've installed the plugin's latest version and am currently working on a project built with the most recent React Native version, but I'm encountering crashes.

Snack or a link to a repository

https://github.com/aslihanturkdonmez/test

Reanimated version

3.5.1

React Native version

0.72.4

Platforms

Android, iOS

JavaScript runtime

Hermes

Workflow

React Native (without Expo)

Architecture

Paper (Old Architecture)

Build type

Release mode

Device

iOS simulator

Device model

iPhone 14 pro (16.2)

Acknowledgements

Yes

uugan0486 commented 1 year ago

I'm having the same problem with crash message "maximum call stack size exceeded" on iOS. Problem goes away by rolling back to 3.4.2.

n-ii-ma commented 1 year ago

Same issue here on Android:

com.swmansion.reanimated.AndroidUIScheduler.triggerUI SourceFile
com.swmansion.reanimated.AndroidUIScheduler$1.run
com.swmansion.reanimated.AndroidUIScheduler$2.runGuarded
com.facebook.react.bridge.GuardedRunnable.run
android.os.Handler.handleCallback Handler.java:942
android.os.Handler.dispatchMessage Handler.java:99
android.os.Looper.loopOnce Looper.java:226
android.os.Looper.loop Looper.java:313
android.app.ActivityThread.main ActivityThread.java:8762
java.lang.reflect.Method.invoke Method.java
com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run RuntimeInit.java:604
com.android.internal.os.ZygoteInit.main ZygoteInit.java:1067

Reverting back to v3.4.2 fixes the problem.

ranaavneet commented 1 year ago

+1

efstathiosntonas commented 1 year ago

same here, only on release scheme, debug works fine.

souna23 commented 1 year ago

the same

aslihanturkdonmez commented 1 year ago

I'm having the same problem with crash message "maximum call stack size exceeded" on iOS. Problem goes away by rolling back to 3.4.2.

It worked, thank you.

efstathiosntonas commented 1 year ago

Did some tests, all versions >= 3.5.0-nightly-20230908-073b64568 fail in release mode.

I think there's something going on with createAnimatedComponent, app works fine and the moment I load a component with it it crashes

efstathiosntonas commented 1 year ago

I think this is the offending PR: https://github.com/software-mansion/react-native-reanimated/pull/5053, the rest of commit history between 20230907 and 0908 is just typings refactor.

ranaavneet commented 1 year ago

@efstathiosntonas Could you create a hotfix patch for this as well like you created for #5061 😊

efstathiosntonas commented 1 year ago

@ranaavneet I'm still trying to figure out what is causing it

kabirbaidhya commented 1 year ago

We're seeing this crash in Android too. +1

angusryer commented 1 year ago

Same. react-native-reanimated v3.5.1, react native 0.72.4. Crashing on release scheme iOS only, Android seems to be okay. Mine crashes with the Max Callstack Size Exceeded error whenever an animation is triggered.

uugan0486 commented 1 year ago

Did some tests, all versions >= 3.5.0-nightly-20230908-073b64568 fail in release mode.

I think there's something going on with createAnimatedComponent, app works fine and the moment I load a component with it it crashes

For me, it's the newer versions >= 3.5.0-nightly-20230904-dbfef8ba4 fail in release mode.

efstathiosntonas commented 1 year ago

@aurotones apply this patch and it will work: https://github.com/software-mansion/react-native-reanimated/issues/5061#issuecomment-1714548068

uugan0486 commented 1 year ago

@efstathiosntonas but i was on 3.5.1, downgrading to 3.5.0 was same so i was keep downgrading till 3.5.0-nightly-20230903-79201c8c0 is working for me on both platform built by CI/CD.

efstathiosntonas commented 1 year ago

Latest working nightly on release mode is 20230907, install and patch this version using patch-package otherwise it crashes because _IS_FABRIC is undefined.

20230907 is the same as 3.5.1, everything above this version has some typings improvements and some files moved around.

uugan0486 commented 1 year ago

Latest working nightly on release is 20230907, install and patch this version using patch-package otherwise it crashes because _IS_FABRIC is undefined.

20230907 is the same as 3.5.1, everything above this version has some typings improvements and some files moved around.

oh that's what you meant, got it.

ranaavneet commented 1 year ago

Hi @efstathiosntonas , any luck on finding what caused this ?

@Latropos @piaskowyk

ravindraguptacapgemini commented 1 year ago

+1

Redseb commented 1 year ago

Latest working nightly on release mode is 20230907, install and patch this version using patch-package otherwise it crashes because _IS_FABRIC is undefined.

20230907 is the same as 3.5.1, everything above this version has some typings improvements and some files moved around.

Hi @efstathiosntonas it seems that the issue still occurs on 3.5.1, I think it's related to #5075

efstathiosntonas commented 1 year ago

The offending PR is definitely this one: https://github.com/software-mansion/react-native-reanimated/pull/4794

after reverting it there's no crash.

efstathiosntonas commented 1 year ago

ok folks, here's the patch, what a nasty bug 😄 ...

note: the typings are throwing errors because of this change, at least it works 💯

react-native-reanimated+3.5.1.patch

diff --git a/node_modules/react-native-reanimated/src/reanimated2/threads.ts b/node_modules/react-native-reanimated/src/reanimated2/threads.ts
index e95bafd..14abbd7 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/threads.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/threads.ts
@@ -204,7 +204,7 @@ export function runOnJS<Args extends unknown[], ReturnValue>(
           : (fun as () => ReturnValue)
       );
   }
-  if ('__workletHash' in fun) {
+  if (fun.__workletHash) {
     // If `fun` is a worklet, we schedule a call of a remote function `runWorkletOnJS`
     // and pass the worklet as a first argument followed by original arguments.

@@ -214,7 +214,7 @@ export function runOnJS<Args extends unknown[], ReturnValue>(
         ...args
       );
   }
-  if ('__remoteFunction' in fun) {
+  if (fun.__remoteFunction) {
     // In development mode the function provided as `fun` throws an error message
     // such that when someone accidentally calls it directly on the UI runtime, they
     // see that they should use `runOnJS` instead. To facilitate that we put the
efstathiosntonas commented 1 year ago

@tjzel @tomekzaw @piaskowyk in example app, Worklet runtime -> runOnUI/runOnJS:

tjzel commented 1 year ago

Thank you @efstathiosntonas. It's something we fought with and fixed in a couple of places, but didn't think about bigger picture and look for other places in the code.

The problem is with Cpp HostObjects, they always return true for in operator in JS and now we have more situations where those can be used as worklets. Therefore the only proper check is actually checking if value is truthy.

If you want you can open a PR with the changes you posted above and I will commit some more fixes of this if necessary.

Thank you very much again!

tjzel commented 1 year ago

@efstathiosntonas Note here about logging, console.log on UI thread will attempt to convert the object to a shareable - use _log function instead (see https://github.com/software-mansion/react-native-reanimated/blob/main/src/reanimated2/core.ts). I think it's actually bugged anyway when I think about it now, since double console.log would potentially result in an error - but I need to check it.

efstathiosntonas commented 1 year ago

@tjzel that's why I deleted the comment above yours about console.log 😄 , it smelled bad

AndreiBehel commented 1 year ago

@tjzel Any chanse to release hotfix for this bug?

tjzel commented 1 year ago

Definitely, I'm testing it right now (waiting for the app to build)

MrLibya commented 1 year ago

@efstathiosntonas Nice work, Based on your solution here's full patch

diff --git a/node_modules/react-native-reanimated/src/animationBuilder.tsx b/node_modules/react-native-reanimated/src/animationBuilder.tsx
index 8204dcd..55d1f19 100644
--- a/node_modules/react-native-reanimated/src/animationBuilder.tsx
+++ b/node_modules/react-native-reanimated/src/animationBuilder.tsx
@@ -35,7 +35,7 @@ export function maybeBuild(
   const isAnimationBuilder = (
     value: ILayoutAnimationBuilder | LayoutAnimationFunction | Keyframe
   ): value is ILayoutAnimationBuilder =>
-    'build' in layoutAnimationOrBuilder &&
+    layoutAnimationOrBuilder.build &&
     typeof layoutAnimationOrBuilder.build === 'function';

   if (isAnimationBuilder(layoutAnimationOrBuilder)) {
diff --git a/node_modules/react-native-reanimated/src/reanimated2/component/FlatList.tsx b/node_modules/react-native-reanimated/src/reanimated2/component/FlatList.tsx
index 3687f47..41e8f93 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/component/FlatList.tsx
+++ b/node_modules/react-native-reanimated/src/reanimated2/component/FlatList.tsx
@@ -69,7 +69,7 @@ export const ReanimatedFlatList = forwardRef(
     // react-native defaults it to 50 for FlatLists.
     // We set it to 1 so we have peace until
     // there are 960 fps screens.
-    if (!('scrollEventThrottle' in restProps)) {
+    if (!(restProps.scrollEventThrottle)) {
       restProps.scrollEventThrottle = 1;
     }

diff --git a/node_modules/react-native-reanimated/src/reanimated2/component/ScrollView.tsx b/node_modules/react-native-reanimated/src/reanimated2/component/ScrollView.tsx
index ad9a9b4..e14e638 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/component/ScrollView.tsx
+++ b/node_modules/react-native-reanimated/src/reanimated2/component/ScrollView.tsx
@@ -45,7 +45,7 @@ export const AnimatedScrollView: AnimatedScrollView = forwardRef(
     // to have continuous scroll events.
     // We set it to 1 so we have peace until
     // there are 960 fps screens.
-    if (!('scrollEventThrottle' in restProps)) {
+    if (!(restProps.scrollEventThrottle)) {
       restProps.scrollEventThrottle = 1;
     }

diff --git a/node_modules/react-native-reanimated/src/reanimated2/layoutReanimation/animationBuilder/Keyframe.ts b/node_modules/react-native-reanimated/src/reanimated2/layoutReanimation/animationBuilder/Keyframe.ts
index f2a10fd..d20359b 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/layoutReanimation/animationBuilder/Keyframe.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/layoutReanimation/animationBuilder/Keyframe.ts
@@ -254,7 +254,7 @@ class InnerKeyframe implements IEntryExitAnimationBuilder {
               )
         );
         if (key.includes('transform')) {
-          if (!('transform' in animations)) {
+          if (!(animations.transform)) {
             animations.transform = [];
           }
           // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
diff --git a/node_modules/react-native-reanimated/src/reanimated2/shareables.ts b/node_modules/react-native-reanimated/src/reanimated2/shareables.ts
index f578032..10abf6e 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/shareables.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/shareables.ts
@@ -255,7 +255,7 @@ type RemoteFunction<T> = {

 function isRemoteFunction<T>(value: object): value is RemoteFunction<T> {
   'worklet';
-  return '__remoteFunction' in value;
+  return Boolean(value.__remoteFunction);
 }

 export function makeShareableCloneOnUIRecursive<T>(
diff --git a/node_modules/react-native-reanimated/src/reanimated2/threads.ts b/node_modules/react-native-reanimated/src/reanimated2/threads.ts
index e95bafd..14abbd7 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/threads.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/threads.ts
@@ -204,7 +204,7 @@ export function runOnJS<Args extends unknown[], ReturnValue>(
           : (fun as () => ReturnValue)
       );
   }
-  if ('__workletHash' in fun) {
+  if (fun.__workletHash) {
     // If `fun` is a worklet, we schedule a call of a remote function `runWorkletOnJS`
     // and pass the worklet as a first argument followed by original arguments.

@@ -214,7 +214,7 @@ export function runOnJS<Args extends unknown[], ReturnValue>(
         ...args
       );
   }
-  if ('__remoteFunction' in fun) {
+  if (fun.__remoteFunction) {
     // In development mode the function provided as `fun` throws an error message
     // such that when someone accidentally calls it directly on the UI runtime, they
     // see that they should use `runOnJS` instead. To facilitate that we put the
diff --git a/node_modules/react-native-reanimated/src/reanimated2/valueUnpacker.ts b/node_modules/react-native-reanimated/src/reanimated2/valueUnpacker.ts
index d46d04c..5fef544 100644
--- a/node_modules/react-native-reanimated/src/reanimated2/valueUnpacker.ts
+++ b/node_modules/react-native-reanimated/src/reanimated2/valueUnpacker.ts
@@ -67,7 +67,7 @@ See \`https://docs.swmansion.com/react-native-reanimated/docs/guides/troubleshoo
 }

 if (__DEV__ && IS_NATIVE) {
-  if (!('__workletHash' in valueUnpacker)) {
+  if (!(valueUnpacker.__workletHash)) {
     throw new Error('[Reanimated] `valueUnpacker` is not a worklet');
   }
   // @ts-ignore TODO TYPESCRIPT
efstathiosntonas commented 1 year ago

@MrLibya thanks, let's hold on though since it might need more changes on other files too, this was deeper than it seemed in the first place. Let's wait @tjzel to release it with proper typings, it won't take long.

tjzel commented 1 year ago

@MrLibya Thanks, but there is no need to change it everywhere in the code, only in places when we can get a HostObject.

tjzel commented 1 year ago

Unfortunately I'm not getting any crashes on Release with your reproduction on iOS simulator @aslihanturkdonmez. If someone has another repro I'm happy to take it.

ravindraguptacapgemini commented 1 year ago

When we can expect new version with a fix for this crash?

itsmesubham commented 1 year ago

any hotfix for this?

ravindraguptacapgemini commented 1 year ago

@efstathiosntonas @MrLibya any timeline for next release with fix?

baesumin commented 1 year ago

TT

efstathiosntonas commented 1 year ago

Hey folks, 3.5.2 is out!

tjzel commented 1 year ago

Fixed in 3.5.2

ravindraguptacapgemini commented 1 year ago

Getting issue with the babel plugin version Simulator Screenshot - iPhone 14 - 2023-09-15 at 21 05 39

tjzel commented 1 year ago

@ravindraguptacapgemini I strongly suggest visiting the link provided in error message - solution is there.

ravindraguptacapgemini commented 1 year ago

@tjzel it did not work initially, I restarted my system then it worked. Thanks!

itsmesubham commented 1 year ago

Thanks a lot for the fix it was just in time :P

chenweigh commented 11 months ago

Environment

"react-native-reanimated": "^3.5.4"

Code

const singleTap = () => {
    return Gesture.Tap()
      .enabled(enableSingleTap)
      .numberOfTaps(1)
      .onStart(() => {
        console.log(`gesture:---single tap`)
        onPress?.()
      })
  }
const composed = Gesture.Race(
    longPressGesture(),
    Gesture.Exclusive(doubleTap(), singleTap())
  )

Problem Only release

[javascript log] gesture:---single tap
libc++abi: terminating due to uncaught exception of type facebook::jsi::JSError: _onPress is not a function. (In '_onPress()', '_onPress' is an instance of CallbackObject)

anonymous@
anonymous@[native code]
runWorklet@
runWorklet@[native code]
anonymous@
anonymous@[native code]
handleAndFlushAnimationFrame@
handleAndFlushAnimationFrame@[native code]
lsps9150414 commented 10 months ago

still crashing in Expo development build with --minify using "react-native-reanimated": "^3.5.4". I'm also using expo-router ^2.0.13 which I suspect is related.

dependencies:

"dependencies": {
    "@expo-google-fonts/pt-mono": "^0.2.3",
    "@ptomasroos/react-native-multi-slider": "^2.2.2",
    "@react-native-async-storage/async-storage": "1.18.2",
    "@react-native-firebase/app": "^18.5.0",
    "@react-native-firebase/auth": "^18.5.0",
    "@react-native-firebase/crashlytics": "^18.5.0",
    "@react-native-firebase/firestore": "^18.5.0",
    "@react-native-firebase/functions": "^18.5.0",
    "@react-native-firebase/perf": "^18.5.0",
    "@react-native-firebase/storage": "^18.5.0",
    "@react-native-masked-view/masked-view": "0.2.9",
    "@reduxjs/toolkit": "^1.9.5",
    "@shopify/flash-list": "1.4.3",
    "algoliasearch": "^4.20.0",
    "emoji-regex": "^10.3.0",
    "expo": "^49.0.20",
    "expo-blur": "~12.4.1",
    "expo-build-properties": "~0.8.3",
    "expo-clipboard": "~4.3.1",
    "expo-constants": "~14.4.2",
    "expo-crypto": "~12.4.1",
    "expo-dev-client": "~2.4.12",
    "expo-device": "~5.4.0",
    "expo-image": "~1.3.5",
    "expo-image-manipulator": "~11.3.0",
    "expo-image-picker": "~14.3.2",
    "expo-linear-gradient": "~12.3.0",
    "expo-linking": "~5.0.2",
    "expo-location": "~16.1.0",
    "expo-media-library": "~15.4.1",
    "expo-notifications": "~0.20.1",
    "expo-router": "^2.0.13",
    "expo-sharing": "~11.5.0",
    "expo-splash-screen": "~0.20.5",
    "expo-status-bar": "~1.6.0",
    "expo-updates": "~0.18.17",
    "hex-rgba": "^1.0.2",
    "lodash": "^4.17.21",
    "luxon": "^3.4.3",
    "moti": "^0.27.2",
    "react": "18.2.0",
    "react-async-hook": "^4.0.0",
    "react-dom": "18.2.0",
    "react-native": "0.72.6",
    "react-native-animatable": "^1.4.0",
    "react-native-confirmation-code-field": "^7.3.1",
    "react-native-deck-swiper": "^2.0.16",
    "react-native-elements": "^3.4.3",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-image-colors": "^2.3.0",
    "react-native-modal": "^13.0.1",
    "react-native-reanimated": "^3.5.4",
    "react-native-redash": "^18.1.0",
    "react-native-safe-area-context": "4.6.3",
    "react-native-screens": "~3.22.0",
    "react-native-svg": "13.9.0",
    "react-native-web": "~0.19.6",
    "react-redux": "^8.1.2",
    "redux-persist": "^6.0.0",
    "redux-saga": "^1.2.3",
    "tinycolor2": "^1.6.0",
    "tinygradient": "^1.1.5",
    "validator": "^13.11.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/hex-rgba": "^1.0.1",
    "@types/lodash": "^4.14.198",
    "@types/luxon": "^3.3.2",
    "@types/react": "~18.2.14",
    "@types/validator": "^13.11.1",
    "eslint": "^8.48.0",
    "eslint-config-universe": "^12.0.0",
    "eslint-plugin-react": "^7.33.2",
    "eslint-plugin-react-native": "^4.1.0",
    "react-native-svg-transformer": "^1.1.0",
    "reactotron-react-native": "^5.0.3",
    "reactotron-redux": "^3.1.3",
    "reactotron-redux-saga": "^4.2.3",
    "typescript": "^5.1.3"
  },
alexandr-feschenko commented 7 months ago

I had a similar issue because I passed only a callback for the reducer as the third parameter to withTiming. It works fine when I wrap this callback in runOnJS.

neeleshyadav253 commented 4 months ago

Downgrade @react-navigation/drawer to version 6.6.3:

Upgrade react-native-reanimated to version 3.5.3:

Update package.json: Ensure your package.json includes the specific versions you want to use:

{ "dependencies": { "react-native-reanimated": "3.5.3", "@react-navigation/drawer": "6.6.3", // other dependencies } } Install the specific versions: Run the following commands to install the specific versions of the packages:

npm install react-native-reanimated@3.5.3 @react-navigation/drawer@6.6.3 or if you are using Yarn:

yarn add react-native-reanimated@3.5.3 @react-navigation/drawer@6.6.3 Clear Metro Bundler cache: Clear the cache to avoid any stale data issues:

npx react-native start --reset-cache Rebuild the project:

For Android:

cd android ./gradlew clean cd .. npx react-native run-android

For iOS:

cd ios pod install cd .. npx react-native run-ios Final package.json Here is an example of the final package.json with the updated versions:

{ "name": "YourProjectName", "version": "0.0.1", "private": true, "scripts": { "start": "react-native start", "android": "react-native run-android", "ios": "react-native run-ios", "test": "jest" }, "dependencies": { "react": "17.0.2", "react-native": "0.65.1", "react-native-reanimated": "3.5.3", "@react-navigation/drawer": "6.6.3", // other dependencies }, "devDependencies": { "@babel/core": "^7.12.9", "@babel/runtime": "^7.12.5", "@react-native-community/eslint-config": "^2.0.0", "babel-jest": "^26.6.3", "eslint": "^7.14.0", "jest": "^26.6.3", "metro-react-native-babel-preset": "^0.64.0", "react-test-renderer": "17.0.2" }, "jest": { "preset": "react-native" } }

estiventhneira commented 4 months ago

@neeleshyadav253 thanks for your solution,

"react-native-reanimated": "3.5.3",
"@react-navigation/drawer": "6.6.3",

was the right combination for me, anyways I think someone in software mansion should take a look again on this