react-native-reanimated icon indicating copy to clipboard operation
react-native-reanimated copied to clipboard

Reanimated is not supporting multiple surfaces

Open gosha212 opened this issue 2 months ago • 11 comments

Description

TLDR LayoutAnimationsProxy is not RN Surface aware (and probably other components too) Reproduction Repo The crash happens only on iOS for some reason

Full Description Background: In Wix React Native Navigation we are using multiple surfaces. For example, each modal is a new native modal / dialog and hosts a new surface. When we close the surface with animation and switch to another surface with animation the applications crashes. For some reason it happens only on iOS but not on Android.

Here is the stacktrace:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'RCTComponentViewRegistry: Attempt to query unregistered component.'
*** First throw call stack:
(
	0   CoreFoundation                      0x00000001804c9690 __exceptionPreprocess + 172
	1   libobjc.A.dylib                     0x00000001800937cc objc_exception_throw + 72
	2   Foundation                          0x0000000180e54f4c -[NSMutableDictionary(NSMutableDictionary) classForCoder] + 0
	3   rn773navigation.debug.dylib         0x0000000104f4b840 -[RCTComponentViewRegistry componentViewDescriptorWithTag:] + 524
	4   rn773navigation.debug.dylib         0x0000000104f8df98 _ZL27RCTPerformMountInstructionsRKNSt3__16vectorIN8facebook5react18ShadowViewMutationENS_9allocatorIS3_EEEEP24RCTComponentViewRegistryR41RCTMountingTransactionObserverCoordinatori + 1428
	5   rn773navigation.debug.dylib         0x0000000104f8d9f8 _ZZ41-[RCTMountingManager performTransaction:]ENK3$_1clERKN8facebook5react19MountingTransactionERKNS1_16SurfaceTelemetryE + 80
	6   rn773navigation.debug.dylib         0x0000000104f8d99c _ZNSt3__18__invokeB8de190102IRZ41-[RCTMountingManager performTransaction:]E3$_1JRKN8facebook5react19MountingTransactionERKNS4_16SurfaceTelemetryEEEEDTclclsr3stdE7declvalIT_EEspclsr3stdE7declvalIT	7   rn773navigation.debug.dylib         0x0000000104f8d944 _ZNSt3__128__invoke_void_return_wrapperIvLb1EE6__callB8de190102IJRZ41-[RCTMountingManager performTransaction:]E3$_1RKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEEvDpOT_ + 40
	8   rn773navigation.debug.dylib         0x0000000104f8d910 _ZNSt3__110__function12__alloc_funcIZ41-[RCTMountingManager performTransaction:]E3$_1NS_9allocatorIS2_EEFvRKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEclB8de190102ES9_SC_ + 	9   rn773navigation.debug.dylib         0x0000000104f8c798 _ZNSt3__110__function6__funcIZ41-[RCTMountingManager performTransaction:]E3$_1NS_9allocatorIS2_EEFvRKN8facebook5react19MountingTransactionERKNS6_16SurfaceTelemetryEEEclES9_SC_ + 44
	10  rn773navigation.debug.dylib         0x0000000104d19904 _ZNKSt3__110__function12__value_funcIFvRKN8facebook5react19MountingTransactionERKNS3_16SurfaceTelemetryEEEclB8de190102ES6_S9_ + 76
	11  rn773navigation.debug.dylib         0x0000000104d18b84 _ZNKSt3__18functionIFvRKN8facebook5react19MountingTransactionERKNS2_16SurfaceTelemetryEEEclES5_S8_ + 40
	12  rn773navigation.debug.dylib         0x0000000104d189b8 _ZNK8facebook5react19TelemetryController15pullTransactionERKNSt3__18functionIFvRKNS0_19MountingTransactionERKNS0_16SurfaceTelemetryEEEESD_SD_ + 300
	13  rn773navigation.debug.dylib         0x0000000104f87afc -[RCTMountingManager performTransaction:] + 588
	14  rn773navigation.debug.dylib         0x0000000104f8782c -[RCTMountingManager initiateTransaction:] + 496
	15  rn773navigation.debug.dylib         0x0000000104f8719c __42-[RCTMountingManager scheduleTransaction:]_block_invoke + 348
	16  rn773navigation.debug.dylib         0x0000000104b3b714 __RCTExecuteOnMainQueue_block_invoke + 40
	17  libdispatch.dylib                   0x00000001009cbec8 _dispatch_call_block_and_release + 24
	18  libdispatch.dylib                   0x00000001009e5798 _dispatch_client_callout + 12
	19  libdispatch.dylib                   0x00000001009db408 _dispatch_main_queue_drain + 1220
	20  libdispatch.dylib                   0x00000001009daf34 _dispatch_main_queue_callback_4CF + 40
	21  CoreFoundation                      0x0000000180428d48 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 12
	22  CoreFoundation                      0x0000000180423754 __CFRunLoopRun + 1920
	23  CoreFoundation                      0x0000000180422b98 CFRunLoopRunSpecific + 536
	24  GraphicsServices                    0x000000019101fd00 GSEventRunModal + 164
	25  UIKitCore                           0x0000000185c5ebb8 -[UIApplication _run] + 796
	26  UIKitCore                           0x0000000185c62f84 UIApplicationMain + 124
	27  UIKitCore                           0x0000000185028f88 block_destroy_helper.14 + 9560
	28  rn773navigation.debug.dylib         0x0000000104826d3c $sSo21UIApplicationDelegateP5UIKitE4mainyyFZ + 128
	29  rn773navigation.debug.dylib         0x0000000104826cac $s15rn773navigation11AppDelegateC5$mainyyFZ + 44
	30  rn773navigation.debug.dylib         0x0000000104826db8 __debug_main_executable_dylib_entry_point + 28
	31  dyld                                0x0000000100ac93d4 start_sim + 20
	32  ???                                 0x0000000100bdeb98 0x0 + 4307413912
)
libc++abi: terminating due to uncaught exception of type NSException

This crash happens only if you have components that implement mountingTransactionWillMount:withSurfaceTelemetry: Like ScrollView because RN have a special logic only for this components:

void RCTMountingTransactionObserverCoordinator::unregisterViewComponentDescriptor(
    const RCTComponentViewDescriptor &componentViewDescriptor,
    SurfaceId surfaceId)
{
  if (!componentViewDescriptor.observesMountingTransactionWillMount &&
      !componentViewDescriptor.observesMountingTransactionDidMount) {
    return;
  }

  auto &surfaceRegistry = registry_[surfaceId];
  assert(surfaceRegistry.count(componentViewDescriptor) == 1);
  surfaceRegistry.erase(componentViewDescriptor);
}

Deeper investigation

  1. Main screen is surface 1
  2. Open a New modal with ScrollView and exit animation. It becomes surface 11
  3. When you close the modal the LayoutAnimationsProxy::pullTransaction will make some changes to the transaction and will not remove all the nodes immediately in the same commit.
  4. Some of the nodes will complete the animation and will be added to deadNodes list in LayoutAnimationsProxy
  5. Once you open another surface or make another commit (State), the next LayoutAnimationsProxy::pullTransaction will add the deadNodes from shadow tree of surface 11 to the transaction of any other surface but not 11. In case of ScrollView it's going to crash because of special handling in RCTMountingTransactionObserverCoordinator

Steps to reproduce

  1. Checkout https://github.com/gosha212/rnn-reanimated-crash-077-078
  2. npm i
  3. cd pod && pod install && cd ..
  4. npx react-native run-ios
  5. Click on 'Show Modal'
  6. Click on 'Close'
  7. Click on 'Show Modal` once again.

Result-> iOS app will crash.

Snack or a link to a repository

https://github.com/gosha212/rnn-reanimated-crash-077-078

Reanimated version

3.18

Worklets version

?

React Native version

0.77.3

Platforms

iOS

JavaScript runtime

Hermes

Workflow

React Native CLI

Architecture

New Architecture (Fabric renderer)

Build type

Debug app & dev bundle

Device

iOS simulator

Host machine

macOS

Device model

iPhone 16

Acknowledgements

Yes

gosha212 avatar Oct 08 '25 15:10 gosha212

Hi @gosha212! Can you try this patch for your specific reanimated version? It fixes the repro, but maybe there are other cases where we would break rn-navigation.

react-native-reanimated+3.18.0.patch

bartlomiejbloniarz avatar Oct 09 '25 13:10 bartlomiejbloniarz

@bartlomiejbloniarz It looks like the items are not being removed correctly

Image

gosha212 avatar Oct 09 '25 16:10 gosha212

This one should do it:

react-native-reanimated+3.18.0.patch

bartlomiejbloniarz avatar Oct 10 '25 13:10 bartlomiejbloniarz

@bartlomiejbloniarz Thank you for the latest patch. This seems to be working on the project we provided. I will keep checking the patch with our major project.

markdevocht avatar Oct 11 '25 17:10 markdevocht

@bartlomiejbloniarz I was able to also apply the patch to our main project and it also works there! Thanks for the super fast work!!

markdevocht avatar Oct 12 '25 12:10 markdevocht

How about memory leaks @markdevocht ?

gosha212 avatar Oct 12 '25 14:10 gosha212

@bartlomiejbloniarz We do have some memory leaks when closing the test app's page the second time. Can you have a look at it?

index.js loaded Unbalanced calls start/end for tag 20 Unbalanced calls start/end for tag 19 app loaded Running "com.myApp.WelcomeScreen" with {"rootTag":1,"initialProps":{"componentId":"Component1"},"fabric":true} App show modal Running "modal" with {"rootTag":11,"initialProps":{"componentId":"Component4"},"fabric":true} Modal WARNING: Logging before InitGoogleLogging() is written to STDERR I1012 17:31:23.850556 1871310848 UIManagerBinding.cpp:164] instanceHandle is null, event of type topMomentumScrollEnd will be dropped show modal Running "modal" with {"rootTag":21,"initialProps":{"componentId":"Component7"},"fabric":true} Modal E1012 17:31:30.637665 1871310848 LeakChecker.cpp:53] [LeakChecker] Surface with id: 11 has leaked 152 components out of 162

markdevocht avatar Oct 12 '25 14:10 markdevocht

I appreciate the efforts into patching the issue however we're experiencing memory leeks as well. Do you happen to have an approximate timeframe of an upcoming patch? Thanks!

martinPandarski avatar Oct 24 '25 09:10 martinPandarski

Has there been any further progress on this issue?

We've collected many reports of this error on Android Firebase: Fatal Exception: com.facebook.react.bridge.RetryableMountingLayerException: Unable to find viewState for tag 2584. Surface stopped: false.

From this error, I found this issue: https://github.com/facebook/react-native/issues/49077, which further suggests that react-native-reanimated might be the problem. Our project also uses React Native Navigation 8.3.2.

Can someone tell me if my problem is related to this error? Or am I going in the wrong direction because my issue is currently occurring on Android devices?

Aikenwu avatar Nov 05 '25 03:11 Aikenwu

Hey, are there any plans to bring this fix to version 4.x.x? I am experiencing a crash on iOS due to this and with 3.18.1 the crash is fixed due to this bugfix being cherrypicked.

dehlen avatar Nov 25 '25 14:11 dehlen

It seems that this problem is still persists on IOS AND Android. Branch https://github.com/Belobopka/wix-rnn-rnlayout-crash2/tree/tab-entering-layout-bug

Crash has gone but we have a problem with entering animation. As you can see the "entering" animation doesn't work correctly for the first try, element is stuck on the top and the animation isn't working. Same if we try to add more elements via "Add" button. UPD: Forgot to mention I tried reanimated 4.x versions with updated react-native but result was the same.

https://github.com/user-attachments/assets/edafef56-eb67-4745-83fb-3ee7a72c22ab

Belobopka avatar Dec 07 '25 18:12 Belobopka