Description
After resolving the initial launch crash, the app successfully booted, but crashed with a fatal EXC_CRASH (SIGABRT) whenever the app attempted to mount or unmount Expo Router's Native Tabs (expo-router/unstable-native-tabs).
Crash Stack Trace Highlight:
text
Thread 0 Crashed
-[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 268
-[RCTViewComponentView unmountChildComponentView:index:] + 2476
RCTPerformMountInstructions
Steps to reproduce
This is a crash occurring deep inside React Native's New Architecture (Fabric) rendering engine. unstable-native-tabs uses react-native-screens under the hood to interface with the native iOS UITabBarController.
On iOS 27 Beta, when navigating or conditionally rendering these native tabs, the native view hierarchy managed by react-native-screens falls out of sync with Fabric's shadow tree. When Fabric issues the RCTPerformMountInstructions to unmount a child view, the native RCTViewComponentView fails an assertion because the view it is trying to unmount is in an unexpected state, triggering the SIGABRT.
How We Solved It (The Workaround)
Since this is a deep native bug between Fabric and react-native-screens on the iOS 27 Beta SDK, we bypassed the buggy native code entirely at the JavaScript level.
We added a platform and version check in our router configuration (app-navigator.tsx and _layout.tsx). If the device is running iOS 27, we dynamically skip rendering the (which triggers NativeTabs) and instead fall back to our custom JavaScript-based @react-navigation/bottom-tabs.
Our Code Solution:
javascript
const IS_IOS = Platform.OS === 'ios';
const iosVersion = parseInt(String(Platform.Version), 10);
// iOS 27 Beta causes react-native-screens to crash in Fabric on unmount.
const IOS_27_BETA_BROKEN = iosVersion === 27;
// iOS 18+ uses NativeTabs. iOS < 18 (and iOS 27 Beta) use the custom JS tab bar fallback.
if (IS_IOS && iosVersion >= 26 && !IOS_27_BETA_BROKEN) {
return ;
}
This avoids invoking the native UITabBarController bridging on iOS 27, keeping the app stable while still giving iOS 18+ users the premium native tabs experience.
Snack or a link to a repository
Since this involves a deep native Fabric crash on a beta iOS version, a Snack cannot reproduce it (Snack does not support New Architecture on iOS 27 beta). However, any standard Expo project using Expo Router's unstable-native-tabs on iOS 27 beta with the New Architecture enabled will reproduce this.
Screens version
4.23.0
React Native version
0.83.6
Platforms
iOS
JavaScript runtime
Hermes
Workflow
Expo managed workflow
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
Real device
Device model
iPhone 17 Pro Max, iOS 27 beta, Xcode 27 beta
Acknowledgements
Yes
Description
After resolving the initial launch crash, the app successfully booted, but crashed with a fatal EXC_CRASH (SIGABRT) whenever the app attempted to mount or unmount Expo Router's Native Tabs (expo-router/unstable-native-tabs).
Crash Stack Trace Highlight:
text
Thread 0 Crashed
-[NSAssertionHandler handleFailureInFunction:file:lineNumber:description:] + 268
-[RCTViewComponentView unmountChildComponentView:index:] + 2476
RCTPerformMountInstructions
Steps to reproduce
This is a crash occurring deep inside React Native's New Architecture (Fabric) rendering engine. unstable-native-tabs uses react-native-screens under the hood to interface with the native iOS UITabBarController.
On iOS 27 Beta, when navigating or conditionally rendering these native tabs, the native view hierarchy managed by react-native-screens falls out of sync with Fabric's shadow tree. When Fabric issues the RCTPerformMountInstructions to unmount a child view, the native RCTViewComponentView fails an assertion because the view it is trying to unmount is in an unexpected state, triggering the SIGABRT.
How We Solved It (The Workaround)
Since this is a deep native bug between Fabric and react-native-screens on the iOS 27 Beta SDK, we bypassed the buggy native code entirely at the JavaScript level.
We added a platform and version check in our router configuration (app-navigator.tsx and _layout.tsx). If the device is running iOS 27, we dynamically skip rendering the (which triggers NativeTabs) and instead fall back to our custom JavaScript-based @react-navigation/bottom-tabs.
Our Code Solution:
javascript
const IS_IOS = Platform.OS === 'ios';
const iosVersion = parseInt(String(Platform.Version), 10);
// iOS 27 Beta causes react-native-screens to crash in Fabric on unmount.
const IOS_27_BETA_BROKEN = iosVersion === 27;
// iOS 18+ uses NativeTabs. iOS < 18 (and iOS 27 Beta) use the custom JS tab bar fallback.
if (IS_IOS && iosVersion >= 26 && !IOS_27_BETA_BROKEN) {
return ;
}
This avoids invoking the native UITabBarController bridging on iOS 27, keeping the app stable while still giving iOS 18+ users the premium native tabs experience.
Snack or a link to a repository
Since this involves a deep native Fabric crash on a beta iOS version, a Snack cannot reproduce it (Snack does not support New Architecture on iOS 27 beta). However, any standard Expo project using Expo Router's unstable-native-tabs on iOS 27 beta with the New Architecture enabled will reproduce this.
Screens version
4.23.0
React Native version
0.83.6
Platforms
iOS
JavaScript runtime
Hermes
Workflow
Expo managed workflow
Architecture
Fabric (New Architecture)
Build type
Debug mode
Device
Real device
Device model
iPhone 17 Pro Max, iOS 27 beta, Xcode 27 beta
Acknowledgements
Yes