Skip to content

[iOS][New Arch] Fatal crash (std::terminate / EXC_CRASH SIGABRT) in RNSSafeAreaViewComponentView::updateState triggered by iOS Password AutoFill bar #4175

Description

@lucasbriguenti

Description

On iOS 26.5 (and likely iOS 18.x) with the New Architecture (Fabric), the app crashes with
EXC_CRASH (SIGABRT) / std::terminate() when the user focuses an email or password field
that triggers the iOS Password AutoFill suggestion bar (the QuickType bar with credentials
from the iOS "Passwords" app appearing above the keyboard).

The crash is fatal, happens on Thread 0 (main thread), and is not catchable by JS-level error
boundaries. It is reproducible consistently when using the native iOS AutoFill flow on a login
screen that contains a SafeAreaView from react-native-screens.

Root cause analysis

When the iOS Password AutoFill bar appears above the keyboard, the OS changes windowInsets,
which triggers UIView's safeAreaInsetsDidChange. RNSScreenView intercepts this via
`-[RNSScreenView safeAreaInsetsDidChange]` (RNSScreen.mm:1172) and posts an
RNSSafeAreaDidChange NSNotification. RNSSafeAreaViewComponentView receives this notification
and calls updateState, which uses EventQueue::UpdateMode::unstable_Immediate.

unstable_Immediate causes the state update — and consequently ShadowTree::commit — to run
synchronously on the main thread. If a Fabric layout pass or mounting transaction is already
in progress at that instant (which is the case during the AutoFill bar appearance, as the keyboard
layout change drives simultaneous RCTMountingManager::initiateTransaction), the ShadowNode
being cloned by ConcreteComponentDescriptor::cloneProps is in an intermediate state. This
causes RawPropsParser::preparse (RawPropsParser.cpp:98) to encounter invalid prop types,
throwing a folly::TypeError which propagates as an unhandled C++ exception and terminates the
process via FIRCLSTerminateHandler / _objc_terminate.

The unstable_Immediate flag was introduced for safe area updates as a side effect of PR #3274
(SplitView synchronous updates), and the #if REACT_NATIVE_VERSION_MINOR >= 82 guard was
removed in PR #4062, making it unconditional in main.

Crash stack (Thread 0)

0   libsystem_kernel.dylib        __pthread_kill + 8
1   libsystem_pthread.dylib       pthread_kill + 268
2   libsystem_c.dylib             abort + 160
3   libc++abi.dylib               demangling_terminate_handler() + 272
4   libobjc.A.dylib               _objc_terminate() + 172
5   App                           FIRCLSTerminateHandler() (FIRCLSException.mm:466)
6   libc++abi.dylib               std::terminate() + 108
7   App                           facebook::react::RawPropsParser::preparse(facebook::react::RawProps const&) const (RawPropsParser.cpp:98)
8   App                           facebook::react::ConcreteComponentDescriptor<facebook::react::ViewShadowNode>::cloneProps(...) (ConcreteComponentDescriptor.h:115)
9   App                           facebook::react::ShadowNode::clone(...) (ShadowNode.cpp:148)
10  App                           facebook::react::ShadowNode::cloneTree(...) (ShadowNode.cpp:402)
...
N   App                           facebook::react::ConcreteState<facebook::react::RNSSafeAreaViewState>::updateState(...) (ConcreteState.h:110)
N+1 App                           -[RNSSafeAreaViewComponentView updateState] (RNSSafeAreaViewComponentView.mm:108)
N+2 CoreFoundation                NSNotificationCenter posting
N+3 App                           -[RNSScreenView dispatchSafeAreaDidChangeNotification] (RNSScreen.mm:1162)
N+4 App                           -[RNSScreenView safeAreaInsetsDidChange] (RNSScreen.mm:1172)
N+5 UIKitCore                     -[UIView _safeAreaInsetsDidChangeFromOldInsets:]

Steps to reproduce

  1. Create a login screen with a <SafeAreaView> (from react-native-screens) wrapping the layout.
  2. Add a text input with keyboardType="email-address" and a secureTextEntry input below it.
  3. Run on a real device with iOS 26.5 (also expected on iOS 18.x).
  4. Tap the email field.
  5. When the iOS Password AutoFill bar (credentials suggestion row from the Passwords app) appears above the keyboard → app crashes immediately.

Environment

react-native-screens 4.25.2
react-native 0.83.2
New Architecture enabled (Fabric)
iOS 26.5 (also expected on 18.x)
Devices confirmed iPhone 13 (iPhone14,5), iPhone 12 Pro, iPhone 15
Distribution TestFlight + production App Store

Workaround

Removing UpdateMode::unstable_Immediate from RNSSafeAreaViewComponentView::updateState
makes the state update async again and eliminates the race condition:

--- a/ios/safe-area/RNSSafeAreaViewComponentView.mm
+++ b/ios/safe-area/RNSSafeAreaViewComponentView.mm
@@ -105,13 +105,7 @@ - (void)updateState
   }

   auto newData = facebook::react::RNSSafeAreaViewState{...};
-  _state->updateState(
-      std::move(newData),
-      facebook::react::EventQueue::UpdateMode::unstable_Immediate
-  );
+  _state->updateState(std::move(newData));
 }

Applied locally via patch-package. The tradeoff is one extra async frame before safe area insets
are applied — visually imperceptible in practice.

Notes

  • The crash is not related to react-native-safe-area-context — the failing class is
    RNSSafeAreaViewComponentView from react-native-screens (prefix RNS, not RNC).
  • The unstable_Immediate mode is intentional for SplitView (PR feat(iOS, SplitView): SplitView synchronous updates #3274), but applying it to
    all safe area view updates introduces this reentrancy hazard on the main thread during
    keyboard/inset transitions.
  • A scoped fix could be to guard the unstable_Immediate mode exclusively for
    RNSSplitScreenComponentView, reverting RNSSafeAreaViewComponentView back to async updates.

Metadata

Metadata

Assignees

Labels

close-when-staleThis issue is going to be closed when there is no activity for a whilemissing-infoThe user didn't precise the problem enoughmissing-reproThis issue need minimum repro scenarioplatform:iosIssue related to iOS part of the library

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions