react-native-reanimated: Runtime crash: JSON object value was a NaN when serializing value at "focalX"
Description
The following crash occurs sporadically in production build.
java.lang.RuntimeException: folly::toJson: JSON object value was a NaN when serializing value at "focalX"
at com.facebook.react.bridge.NativeMap.toString(NativeMap.java)
at com.swmansion.reanimated.NativeProxy$EventHandler.receiveEvent(NativeProxy.java)
at com.swmansion.reanimated.NativeProxy$EventHandler.receiveEvent(NativeProxy.java:55)
at com.swmansion.gesturehandler.react.RNGestureHandlerStateChangeEvent.dispatch(RNGestureHandlerStateChangeEvent.java:80)
at com.swmansion.reanimated.NodesManager.handleEvent(NodesManager.java:485)
at com.swmansion.reanimated.NodesManager.onEventDispatch(NodesManager.java:462)
at com.facebook.react.uimanager.events.EventDispatcherImpl.dispatchEvent(EventDispatcherImpl.java:116)
at com.swmansion.gesturehandler.react.RNGestureHandlerModule.onStateChange(RNGestureHandlerModule.java:691)
at com.swmansion.gesturehandler.react.RNGestureHandlerModule.access$300(RNGestureHandlerModule.java:42)
at com.swmansion.gesturehandler.react.RNGestureHandlerModule$1.onStateChange(RNGestureHandlerModule.java:436)
at com.swmansion.gesturehandler.GestureHandler.dispatchStateChange(GestureHandler.java:81)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.onHandlerStateChange(GestureHandlerOrchestrator.java:200)
at com.swmansion.gesturehandler.GestureHandler.moveToState(GestureHandler.java:350)
at com.swmansion.gesturehandler.GestureHandler.cancel(GestureHandler.java:444)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.makeActive(GestureHandlerOrchestrator.java:223)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.tryActivate(GestureHandlerOrchestrator.java:159)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.onHandlerStateChange(GestureHandlerOrchestrator.java:194)
at com.swmansion.gesturehandler.GestureHandler.moveToState(GestureHandler.java:350)
at com.swmansion.gesturehandler.GestureHandler.activate(GestureHandler.java:456)
at com.swmansion.gesturehandler.NativeViewGestureHandler.onHandle(NativeViewGestureHandler.java:87)
at com.swmansion.gesturehandler.GestureHandler.handle(GestureHandler.java:329)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.deliverEventToGestureHandler(GestureHandlerOrchestrator.java:301)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.deliverEventToGestureHandlers(GestureHandlerOrchestrator.java:259)
at com.swmansion.gesturehandler.GestureHandlerOrchestrator.onTouchEvent(GestureHandlerOrchestrator.java:101)
at com.swmansion.gesturehandler.react.RNGestureHandlerRootHelper.dispatchTouchEvent(RNGestureHandlerRootHelper.java:126)
at com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView.dispatchTouchEvent(RNGestureHandlerEnabledRootView.java:36)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:3920)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:3535)
at com.android.internal.policy.DecorView.superDispatchTouchEvent(DecorView.java:913)
at com.android.internal.policy.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1957)
at android.app.Activity.dispatchTouchEvent(Activity.java:4182)
at androidx.appcompat.view.WindowCallbackWrapper.dispatchTouchEvent(WindowCallbackWrapper.java:69)
at com.android.internal.policy.DecorView.dispatchTouchEvent(DecorView.java:871)
at android.view.View.dispatchPointerEvent(View.java:15458)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:7457)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:7233)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6595)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6652)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6618)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:6786)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6626)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:6843)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6599)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:6652)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:6618)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:6626)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:6599)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:9880)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:9718)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:9671)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:10014)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:220)
at android.os.MessageQueue.nativePollOnce(MessageQueue.java)
at android.os.MessageQueue.next(MessageQueue.java:335)
at android.os.Looper.loop(Looper.java:206)
at android.app.ActivityThread.main(ActivityThread.java:8633)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1130)
Expected behavior
It should not crash.
Actual behavior & steps to reproduce
- upgrade react-native-reanimated: from 1.13.2 to 2.2.4 in project
- update
Modify references in the code from (reanimated v1)
const translateX = Animated.interpolate(progress, {
inputRange: [0, 0.5, 0.7, 0.8, 1],
outputRange: [-100, -85, -70, -45, 0],
});
to (reanimated v2)
const translateX = Animated.interpolateNode(
progress as Animated.Adaptable<number>,
{
inputRange: [0, 0.5, 0.7, 0.8, 1],
outputRange: [-100, -85, -70, -45, 0],
},
);
and from
React.useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
easing: Easing.inOut(Easing.ease),
}).start();
}, [fadeAnim]);
to
React.useEffect(() => {
Animated.timing(fadeAnim, {
toValue: 1,
duration: 1000,
easing: EasingNode.inOut(EasingNode.ease),
}).start();
}, [fadeAnim]);
Those are the only 2 references of react-native-reanimated in my app
Package versions
- React Native: 0.66.3
- React Native Reanimated: 2.2.4
- NodeJS: v16.11.1
- Xcode: 13.1
- Java & Gradle: java 15.0.2 2021-01-19 and gradle 6.9
Affected platforms
- Android
- iOS
- Web
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Comments: 15 (9 by maintainers)
@vtoupet We release a new version today night or tomorrow morning 😀 (according to middle Europe time)
fair point about other libraries. The solution in the pr looks good, way better than what I did by replacing the NaNs with nulls in the java code. Happy to see it merged! thanks for your work @tomekzaw
I came up with a fix for the gesture handler library to prevent NaN values in first place. Let’s see what they say about it. https://github.com/software-mansion/react-native-gesture-handler/pull/1853
folly::toJson: JSON object value was a NaN when serializing value at "velocity"->"y"
keeps happening for our users. It seems that it directly happens after an orientation switch has happened and the viewport gets recreated with new dimensions. I’m wondering if this is more a problem with react-native-gesture-handler .Would it make sense to ignore events with which contain
NaN
values? I’d prefer that over crashing the entire app, but this might be specific to us. @piaskowyk