Skip to content

[iOS] EXC_BAD_ACCESS in performOperations from handleRawEvent during screen pop on 4.3.1 #9402

Description

@mtflud

Description

iOS production EXC_BAD_ACCESS (KERN_INVALID_ADDRESS at 0x18) crash on react-native-reanimated@4.3.1 + react-native-worklets@0.8.3 + Fabric. The crash signature is structurally identical to #9293 / #9303 (a mount-time deref of a stale view during a reanimated commit) but is triggered through a different upstream path: react-native-screens' per-frame notifyTransitionProgress event during a native-stack screen pop, not the rAF / AnimationFrameBatchinator::flush() path that #9293 OP described.

The registry-locking fix in 4.3.1 (PRs #9308, #9323; release tagged 2026-05-07) resolved one variant we were hitting (chat-list-scroll EXC_BAD_ACCESS in AnimatedPropsRegistry::update). The screen-pop variant in this report is still happening after upgrading to 4.3.1, in line with @florian-deroo's and @LeCiel's post-fix reports in #9293.

Crash flow

Main-thread stack at the moment of segfault (real production crash from a TestFlight 1.0.9 build cut after the 4.3.1 bump):

0   [Redacted]    RCTPerformMountInstructions               (RCTMountingManager.mm)
10  [Redacted]     -[RCTMountingManager performTransaction:]                (:258)
11   [Redacted]     -[RCTMountingManager initiateTransaction:]               (:246)
12  [Redacted]     -[RCTSurfacePresenter schedulerShouldRenderTransactions:] (:307)
14  [Redacted]    facebook::react::Scheduler::uiManagerDidFinishTransaction        (Scheduler.cpp:279)
15  [Redacted]    facebook::react::UIManager::shadowTreeDidFinishTransaction       (UIManager.cpp:637)
16  [Redacted]    facebook::react::ShadowTree::notifyDelegatesOfUpdates            (ShadowTree.cpp:426)
17  [Redacted]    facebook::react::ShadowTreeRegistry::visit                       (ShadowTreeRegistry.cpp:50)
20  [Redacted]    reanimated::ReanimatedModuleProxy::performOperations()           (ReanimatedModuleProxy.cpp:673)
21  [Redacted]    reanimated::ReanimatedModuleProxy::handleRawEvent                (ReanimatedModuleProxy.cpp:619)
22  [Redacted]    -[ReanimatedModule attachReactEventListener:]::block-literal::$_0::operator()
30  [Redacted]    facebook::react::EventListenerContainer::willDispatchEvent
31  [Redacted]    facebook::react::EventDispatcher::dispatchEvent
32  [Redacted]    facebook::react::EventEmitter::dispatchEvent
34  [Redacted]    facebook::react::RNSScreenEventEmitter::onTransitionProgress     (EventEmitters.cpp:315)
35  [Redacted]    -[RNSScreenView notifyTransitionProgress:closing:goingForward:]  (RNSScreen.mm:790)
36  [Redacted]    -[RNSScreen notifyTransitionProgress:closing:goingForward:]      (RNSScreen.mm:1983)
37  QuartzCore CA::Display::DisplayLinkItem::dispatch_
38  QuartzCore CA::Display::DisplayLink::dispatch_items
39  QuartzCore CA::Display::DisplayLink::dispatch_deferred_display_links
  • Exception: EXC_BAD_ACCESS (SIGSEGV) / KERN_INVALID_ADDRESS at 0x0000000000000018
  • The faulting load is a null+offset deref — classic stale-pointer-to-deallocated-object signature inside the mounting layer.

What we believe is happening

  1. The user pops a native-stack screen (react-native-screens@4.25.0, no Reanimated*Stack wrapping — vanilla @react-navigation/native-stack).
  2. UIKit's CADisplayLink ticks during the transition.
  3. RNSScreen::notifyTransitionProgress fires the Fabric onTransitionProgress event every frame (see RNSScreen.mm:1797 → :635; the call is unconditional, no listener gating).
  4. The event flows through EventDispatcher::dispatchEventEventListenerContainer::willDispatchEvent → reanimated's listener → ReanimatedModuleProxy::handleRawEvent.
  5. Inside handleRawEvent, control reaches performOperations() at line 619 — i.e. either (a) StaticFeatureFlags::ENABLE_SHARED_ELEMENT_TRANSITIONS is disabled at build time so the early-return branch is removed, or (b) a JS handler is registered for onTransitionProgress on this view tag (e.g. via useReanimatedTransitionProgress) and the function fell through past isAnyHandlerWaitingForEvent.
  6. performOperations() flushes layoutAnimationFlushRequests_ at line 673 and visits each surface's shadow tree.
  7. ShadowTree::notifyDelegatesOfUpdates commits a mount transaction. RCTPerformMountInstructions applies a queued mutation against a RCTViewComponentView whose backing UIView is mid-teardown by the screen pop — null deref.

The mutation being flushed is queued by in-flight withSpring/withTiming animations that have not been cancelled before the unmount transaction runs. We confirmed this empirically: the only application-side mitigation that has stopped the crash so far in our internal testing is draining all SharedValues tied to animated styles in the popping subtree before the transition starts (cancelling animations + gating event-driven worklets via a closing flag on navigation.addListener('beforeRemove')).

Why we think this is a follow-up to #9293, not the same bug

Happy to be told this is the same bug and to comment on #9293 instead — flagging as a separate issue to make the screen-pop path visible.

Steps to reproduce

We do not have a deterministic standalone repro and we cannot reproduce on a developer machine (debug builds, internal staging, simulators, or the same physical device with the same account all fail to trigger). The crash is observed in production telemetry across multiple unrelated users; some users reproduce it 100% of the time on every screen, others never. We have not isolated the personal axis.

Snack or a link to a repository

N/A

Reanimated version

4.3.1

Worklets version

0.8.3

React Native version

0.83.9

Platforms

iOS

JavaScript runtime

Hermes

Workflow

Expo Dev Client

Architecture

New Architecture (Fabric renderer)

Reanimated feature flags

No

React Native release level

Stable

Build type

Release app & production bundle

Device

Real device

Host machine

macOS

Device model

iPhone17,1

Acknowledgements

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    Missing reproThis issue need minimum repro scenarioPlatform: iOSThis issue is specific to iOS

    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