Reanimated is not supporting multiple surfaces
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
- Main screen is surface 1
- Open a New modal with
ScrollViewand exit animation. It becomes surface 11 - When you close the modal the
LayoutAnimationsProxy::pullTransactionwill make some changes to the transaction and will not remove all the nodes immediately in the same commit. - Some of the nodes will complete the animation and will be added to
deadNodeslist inLayoutAnimationsProxy - Once you open another surface or make another commit (State), the next
LayoutAnimationsProxy::pullTransactionwill add thedeadNodesfrom shadow tree of surface 11 to the transaction of any other surface but not 11. In case ofScrollViewit's going to crash because of special handling inRCTMountingTransactionObserverCoordinator
Steps to reproduce
- Checkout https://github.com/gosha212/rnn-reanimated-crash-077-078
npm icd pod && pod install && cd ..npx react-native run-ios- Click on 'Show Modal'
- Click on 'Close'
- 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
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.
@bartlomiejbloniarz It looks like the items are not being removed correctly
@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.
@bartlomiejbloniarz I was able to also apply the patch to our main project and it also works there! Thanks for the super fast work!!
How about memory leaks @markdevocht ?
@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
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!
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?
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.
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