(Android - Crash): FragmentManager is already executing transactions
See original GitHub issueDescription
When react native screens are enabled on Android and the architecture is based on a single Activity
plus React native is loaded in a Fragment, there’s a crash when navigating and restoring the fragment state.
Having a single Activity
app and using Fragments
with navigation components as describe here brings us to load React Native apps on a Fragment
. We also want to enable React native screens, however, when enabled on Android, there’s the following crash:
java.lang.RuntimeException: Unable to resume activity {com.swmansion.rnscreens.example/com.swmansion.rnscreens.example.MainActivity}: java.lang.IllegalStateException: FragmentManager is already executing transactions at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4445) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4477) at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2067) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:223) at android.app.ActivityThread.main(ActivityThread.java:7697) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:952) Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1686) at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1716) at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:323) at com.swmansion.rnscreens.ScreenContainer.removeMyFragments(ScreenContainer.kt:216) at com.swmansion.rnscreens.ScreenContainer.onDetachedFromWindow(ScreenContainer.kt:228) at android.view.View.dispatchDetachedFromWindow(View.java:20538) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3942) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3934) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3934) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5560) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:5531) at android.view.ViewGroup.removeView(ViewGroup.java:5462) at androidx.fragment.app.FragmentContainerView.removeView(FragmentContainerView.kt:288) at androidx.fragment.app.SpecialEffectsController$Operation$State.applyState(SpecialEffectsController.java:470) at androidx.fragment.app.DefaultSpecialEffectsController.applyContainerChanges(DefaultSpecialEffectsController.java:822) at androidx.fragment.app.DefaultSpecialEffectsController$1.run(DefaultSpecialEffectsController.java:111) at androidx.fragment.app.SpecialEffectsController$Operation.complete(SpecialEffectsController.java:713) at androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete(SpecialEffectsController.java:770) at androidx.fragment.app.SpecialEffectsController$Operation.completeSpecialEffect(SpecialEffectsController.java:690) at androidx.fragment.app.DefaultSpecialEffectsController$SpecialEffectsInfo.completeSpecialEffect(DefaultSpecialEffectsController.java:855) at androidx.fragment.app.DefaultSpecialEffectsController.startAnimations(DefaultSpecialEffectsController.java:154) at androidx.fragment.app.DefaultSpecialEffectsController.executeOperations(DefaultSpecialEffectsController.java:123) at androidx.fragment.app.SpecialEffectsController.executePendingOperations(SpecialEffectsController.java:306) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:1903) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1814) at androidx.fragment.app.FragmentManager.execPendingActions(FragmentManager.java:1751) at androidx.fragment.app.Fragment.performResume(Fragment.java:3177) at androidx.fragment.app.FragmentStateManager.resume(FragmentStateManager.java:606) at androidx.fragment.app.FragmentStateManager.moveToExpectedState(FragmentStateManager.java:285) 2022-07-03 22:00:08.008 30152-30152/com.swmansion.rnscreens.example E/AndroidRuntime: at androidx.fragment.app.FragmentStore.moveToExpectedState(FragmentStore.java:113) at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1424) at androidx.fragment.app.FragmentManager.dispatchStateChange(FragmentManager.java:2968) at androidx.fragment.app.FragmentManager.dispatchResume(FragmentManager.java:2900) at androidx.fragment.app.FragmentController.dispatchResume(FragmentController.java:285) at androidx.fragment.app.FragmentActivity.onResumeFragments(FragmentActivity.java:334) at androidx.fragment.app.FragmentActivity.onPostResume(FragmentActivity.java:323) at androidx.appcompat.app.AppCompatActivity.onPostResume(AppCompatActivity.java:204) at android.app.Activity.performResume(Activity.java:8160) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4435)
The reason of the crash seems to be:
- When setting up
ScreenContainer
it receives theFragmentManager
from the Activity at some point. - This same
FragmentManager
is used by the Navigation Components to navigate between fragments. - When the
Fragment
that has react native tries to recover the state after a navigation, it tries to use theActivity
FragmentManager
which is already in use.
Screenshots
Steps To Reproduce
To reproduce, I’ve recreated in the Example
app a common use case: Load React native, put the app in the background and trigger a deep link. I’ve prepared the Example
to do this so the steps are:
- Launch the Example app
- Tap Stack Presentation
- Tap Form Sheet
- Put some values in the form.
- Background the app
- Launch the following adb comand:
adb shell am start -W -a android.intent.action.VIEW -d "screens://screens" com.swmansion.rnscreens.example
Expected behavior
The react native screen should display without a crash
Actual behavior
Crash with the above stack trace
Reproduction
To reproduce the crash I’ve forked react-native-screens
github project and modified the example with the described architecture. The project can be found here: https://github.com/luislukas/react-native-screens
I reported this issue originally on https://github.com/software-mansion/react-native-screens/issues/819 but due to our architecture we had to disable react-native-screens
. We would like to enable them now so any hint/help would be appreciated.
Platform
- iOS
- Android
- Web
- Windows
- tvOS
Architecture
I’ve forked the react-native-screens
and added the Navigation Componentes plus Fragments
architecture described aboved.
- Paper
- Fabric
Workflow
- Managed workflow
- Bare workflow
Package versions
I’m using a fork of this project just changing the Android project architecture.
package | version |
---|---|
react-native | |
@react-navigation/native | |
@react-navigation/native-stack | |
react-native-screens | |
react-native-safe-area-context | |
react-native-gesture-handler | |
react-native-reanimated | |
expo |
Issue Analytics
- State:
- Created a year ago
- Comments:15 (4 by maintainers)
Top GitHub Comments
Hi @nvu @luislukas! I dived into it and came up with (I hope) proper solution: https://github.com/software-mansion/react-native-screens/pull/1553
Would you mind checking these changes out and letting me know whether it works for you?
You can put following line in your
package.json
@kkafar I’m unable to reproduce the issue and don’t know where it is happening since this issue is happening in production. Please find the crash log below
Caused by java.lang.IllegalStateException: FragmentManager is already executing transactions at androidx.fragment.app.FragmentManager.ensureExecReady(FragmentManager.java:1931) at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1967) at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311) at com.swmansion.rnscreens.ScreenContainer.onUpdate(ScreenContainer.kt:366) at com.swmansion.rnscreens.ScreenContainer.performUpdates(ScreenContainer.kt:311) at com.swmansion.rnscreens.ScreenContainer.performUpdatesNow(ScreenContainer.kt:303) at com.swmansion.rnscreens.ScreenContainer.notifyChildUpdate(ScreenContainer.kt:87) at com.swmansion.rnscreens.Screen.setActivityState(Screen.kt:132) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:49) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:34) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:21) at com.facebook.react.viewmanagers.RNSScreenManagerDelegate.setProperty(RNSScreenManagerDelegate.java:81) at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:46) at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:84) at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:142) at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:306) at com.facebook.react.uimanager.UIManagerModule.synchronouslyUpdateViewOnUIThread(UIManagerModule.java:402) at com.facebook.react.animated.PropsAnimatedNode.updateView(PropsAnimatedNode.java:118) at com.facebook.react.animated.NativeAnimatedNodesManager.updateNodes(NativeAnimatedNodesManager.java:747) at com.facebook.react.animated.NativeAnimatedNodesManager.handleEvent(NativeAnimatedNodesManager.java:600) at com.facebook.react.animated.NativeAnimatedNodesManager.onEventDispatch(NativeAnimatedNodesManager.java:562) at com.facebook.react.uimanager.events.EventDispatcherImpl.dispatchEvent(EventDispatcherImpl.java:116) at com.reactnativepagerview.PagerViewViewManager$createViewInstance$1$1.onPageScrolled(PagerViewViewManager.kt:43) at androidx.viewpager2.widget.CompositeOnPageChangeCallback.onPageScrolled(CompositeOnPageChangeCallback.java:59) at androidx.viewpager2.widget.CompositeOnPageChangeCallback.onPageScrolled(CompositeOnPageChangeCallback.java:59) at androidx.viewpager2.widget.ScrollEventAdapter.dispatchScrolled(ScrollEventAdapter.java:438) at androidx.viewpager2.widget.ScrollEventAdapter.onScrollStateChanged(ScrollEventAdapter.java:134) at androidx.recyclerview.widget.RecyclerView.dispatchOnScrollStateChanged(RecyclerView.java:5210) at androidx.recyclerview.widget.RecyclerView.setScrollState(RecyclerView.java:1550) at androidx.recyclerview.widget.RecyclerView.stopScroll(RecyclerView.java:2493) at androidx.recyclerview.widget.RecyclerView.onDetachedFromWindow(RecyclerView.java:2998) at android.view.View.dispatchDetachedFromWindow(View.java:14598) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3074) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.dispatchDetachedFromWindow(ViewGroup.java:3066) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4606) at android.view.ViewGroup.removeViewInternal(ViewGroup.java:4579) at android.view.ViewGroup.removeView(ViewGroup.java:4510) at com.swmansion.rnscreens.ScreenContainer.removeView(ScreenContainer.kt:66) at androidx.fragment.app.SpecialEffectsController$Operation$State.applyState(SpecialEffectsController.java:452) at androidx.fragment.app.DefaultSpecialEffectsController.applyContainerChanges(DefaultSpecialEffectsController.java:743) at androidx.fragment.app.DefaultSpecialEffectsController$1.run(DefaultSpecialEffectsController.java:108) at androidx.fragment.app.SpecialEffectsController$Operation.complete(SpecialEffectsController.java:695) at androidx.fragment.app.SpecialEffectsController$FragmentStateManagerOperation.complete(SpecialEffectsController.java:744) at androidx.fragment.app.SpecialEffectsController$Operation.completeSpecialEffect(SpecialEffectsController.java:672) at androidx.fragment.app.DefaultSpecialEffectsController$SpecialEffectsInfo.completeSpecialEffect(DefaultSpecialEffectsController.java:776) at androidx.fragment.app.DefaultSpecialEffectsController.startAnimations(DefaultSpecialEffectsController.java:147) at androidx.fragment.app.DefaultSpecialEffectsController.executeOperations(DefaultSpecialEffectsController.java:120) at androidx.fragment.app.SpecialEffectsController.executePendingOperations(SpecialEffectsController.java:297) at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2202) at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:2106) at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1971) at androidx.fragment.app.BackStackRecord.commitNowAllowingStateLoss(BackStackRecord.java:311) at com.swmansion.rnscreens.ScreenContainer.onUpdate(ScreenContainer.kt:366) at com.swmansion.rnscreens.ScreenContainer.performUpdates(ScreenContainer.kt:311) at com.swmansion.rnscreens.ScreenContainer.performUpdatesNow(ScreenContainer.kt:303) at com.swmansion.rnscreens.ScreenContainer.notifyChildUpdate(ScreenContainer.kt:87) at com.swmansion.rnscreens.Screen.setActivityState(Screen.kt:132) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:47) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:34) at com.swmansion.rnscreens.ScreenViewManager.setActivityState(ScreenViewManager.kt:21) at com.facebook.react.viewmanagers.RNSScreenManagerDelegate.setProperty(RNSScreenManagerDelegate.java:81) at com.facebook.react.uimanager.ViewManagerPropertyUpdater.updateProps(ViewManagerPropertyUpdater.java:46) at com.facebook.react.uimanager.ViewManager.updateProperties(ViewManager.java:84) at com.facebook.react.uimanager.NativeViewHierarchyManager.updateProperties(NativeViewHierarchyManager.java:142) at com.facebook.react.uimanager.UIImplementation.synchronouslyUpdateViewOnUIThread(UIImplementation.java:306) at com.facebook.react.uimanager.UIManagerModule.synchronouslyUpdateViewOnUIThread(UIManagerModule.java:402) at com.facebook.react.animated.PropsAnimatedNode.updateView(PropsAnimatedNode.java:118) at com.facebook.react.animated.NativeAnimatedNodesManager.updateNodes(NativeAnimatedNodesManager.java:747) at com.facebook.react.animated.NativeAnimatedNodesManager.runUpdates(NativeAnimatedNodesManager.java:641) at com.facebook.react.animated.NativeAnimatedModule$1.doFrameGuarded(NativeAnimatedModule.java:263) at com.facebook.react.uimanager.GuardedFrameCallback.doFrame(GuardedFrameCallback.java:29) at com.facebook.react.modules.core.ReactChoreographer$ReactChoreographerDispatcher.doFrame(ReactChoreographer.java:175) at com.facebook.react.modules.core.ChoreographerCompat$FrameCallback$1.doFrame(ChoreographerCompat.java:85) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:858) at android.view.Choreographer.doCallbacks(Choreographer.java:672) at android.view.Choreographer.doFrame(Choreographer.java:605) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:846) at android.os.Handler.handleCallback(Handler.java:742) at android.os.Handler.dispatchMessage(Handler.java:95) at android.os.Looper.loop(Looper.java:157) at android.app.ActivityThread.main(ActivityThread.java:5603) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:774) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:652)