Description
Production crash on iOS: EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) at
-[REANodesManager performOperations] (REANodesManager.mm:127, which
is the _performOperations(); call that invokes
ReanimatedModuleProxy::performOperations() via the block registered
in NativeProxy.mm:47-51).
The crash is triggered on the main thread from the rAF path:
QuartzCore DisplayLink
-> -[AnimationFrameQueue executeQueue:]
-> worklets::AnimationFrameBatchinator::flush() (line 50 in
AnimationFrameBatchinator.cpp, inside the `runSync` loop)
-> WorkletRuntime::runSync<double&>(timestamp)
-> WithRuntimeDecorator<worklets::AroundLock>::call(...)
-> Hermes interprets JS -> Array.prototype.forEach
-> reanimated host function (createHostFunction)
-> -[REANodesManager performOperations] <-- crash
At the same time, the JS thread is blocked on the same
AroundLock/recursive_mutex inside
WorkletRuntime::runSyncSerialized, i.e. a concurrent runOnUISync
call was waiting for the UI runtime lock the main thread held.
This matches the race flagged by the comment in
ReanimatedModuleProxy.cpp:729:
It may happen that performOperations is called on the UI thread
while React Native tries to commit a new tree on the JS thread.
We believe the crash is a null/stale dereference inside
ReanimatedModuleProxy::performOperations() (likely uiManager_ or
the shadow tree for a surface that is being torn down) during the
window described in that comment.
This issue is similar in spirit to #9111 (React commits blocking
reanimated updates), but manifests as a hard crash instead of a
freeze. It may also relate to #6245 (Race condition in
NativeReanimatedModule::performOperations).
Impact
42 unique users, 43 events in the first hours after the release that
upgraded to this stack. Crash rate is trending up. Tagged "Early
crashes" in Crashlytics, i.e. the crash happens soon after app
launch. No such crashes in the previous release on RN 0.84 +
Reanimated 3.x. The only change in the crashing release is the
upgrade to RN 0.85.1 + Reanimated 4.3.0 + worklets 0.8.1.
Steps to reproduce
No deterministic repro; the crash is aggregated from production
telemetry. Given the "Early crashes" tag and the observed pattern
(main thread inside AroundLock + JS thread waiting on the same lock),
the trigger is likely a rapid surface mount/unmount early in app
start (e.g. navigation transition or reanimated-heavy component
mount) racing with the rAF flush. Reanimated is used transitively via
common libraries (react-native-reanimated-carousel,
react-native-bottom-tabs, @gorhom/bottom-sheet,
react-native-sortables, react-native-screens).
Snack or a link to a repository
Not available - production crash aggregated via Crashlytics, no
minimal repro yet. Filing anyway per the guidance in #6245 that a
clear explanation of the race can still be actionable.
Main-thread stack (symbolicated, app-specific frames removed)
0 -[REANodesManager performOperations] + 127 (REANodesManager.mm:127)
1 reanimated::jsi_utils::createHostFunction<...> lambda (jsi.h:1754)
2 std::function<jsi::Value(...)>::operator() (function.h:772)
3 std::function<jsi::Value(...)>::operator() (function.h:772)
4 hermesvm std::function<...>::operator()
5 HermesRuntimeImpl::HFContext::func
6 hermes::vm::NativeFunction::_nativeCall
7 hermes::vm::Interpreter::handleCallSlowPath
8 hermes::vm::Interpreter::interpretFunction<false,false>
9 hermes::vm::Runtime::interpretFunctionImpl
10 hermes::vm::JSFunction::_callImpl
11 hermes::vm::Callable::executeCall3
12 hermes::vm::arrayPrototypeForEach
13 hermes::vm::NativeFunction::_nativeCall
14 hermes::vm::Interpreter::handleCallSlowPath
15 hermes::vm::Interpreter::interpretFunction<false,false>
16 hermes::vm::Runtime::interpretFunctionImpl
17 hermes::vm::JSFunction::_callImpl
18 HermesRuntimeImpl::call
19 jsi::WithRuntimeDecorator<worklets::AroundLock, ...>::call
20 worklets::WorkletRuntime::runSync<double&> (jsi-inl.h:313)
21 worklets::AnimationFrameBatchinator::flush()::$_0
(AnimationFrameBatchinator.cpp:50)
22 -[AnimationFrameQueue executeQueue:]
23 CA::Display::DisplayLinkItem::dispatch_
24 CA::Display::DisplayLink::dispatch_items
25 CA::Display::DisplayLink::dispatch_deferred_display_links
26-37 UIKit / UpdateCycle / CFRunLoop / UIApplicationMain
38 main
JS thread at time of crash (blocked on same lock)
0 __psynch_mutexwait
1 _pthread_mutex_firstfit_lock_wait
2 _pthread_mutex_firstfit_lock_slow
3 std::recursive_mutex::lock()
4 worklets::WorkletRuntime::runSyncSerialized (WorkletRuntime.h:101)
5 worklets::runOnUISync(weak_ptr<WorkletRuntime>, jsi::Runtime&,
jsi::Value const&)
6 Hermes interpreter frames
...
(JS dispatched a runOnUISync call, which is waiting on the same
AroundLock the main thread holds while inside performOperations.)
Reanimated version
4.3.0
Worklets version
0.8.1
React Native version
0.85.1
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native CLI
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
Multiple models (42 distinct users affected); crash is not device-
specific.
Acknowledgements
Yes - searched for similar issues. Closest matches: #9111, #6245,
#7666. Filing a dedicated thread because none of those describe a
reproducible null-deref crash under the 4.3.0 + worklets 0.8.1 + RN
0.85.1 stack, and the crash rate is high enough to warrant tracking
separately.
generated with Claude
Description
Production crash on iOS:
EXC_BAD_ACCESS (KERN_INVALID_ADDRESS)at-[REANodesManager performOperations](REANodesManager.mm:127, whichis the
_performOperations();call that invokesReanimatedModuleProxy::performOperations()via the block registeredin
NativeProxy.mm:47-51).The crash is triggered on the main thread from the rAF path:
At the same time, the JS thread is blocked on the same
AroundLock/recursive_mutex insideWorkletRuntime::runSyncSerialized, i.e. a concurrentrunOnUISynccall was waiting for the UI runtime lock the main thread held.
This matches the race flagged by the comment in
ReanimatedModuleProxy.cpp:729:We believe the crash is a null/stale dereference inside
ReanimatedModuleProxy::performOperations()(likelyuiManager_orthe shadow tree for a surface that is being torn down) during the
window described in that comment.
This issue is similar in spirit to #9111 (React commits blocking
reanimated updates), but manifests as a hard crash instead of a
freeze. It may also relate to #6245 (Race condition in
NativeReanimatedModule::performOperations).
Impact
42 unique users, 43 events in the first hours after the release that
upgraded to this stack. Crash rate is trending up. Tagged "Early
crashes" in Crashlytics, i.e. the crash happens soon after app
launch. No such crashes in the previous release on RN 0.84 +
Reanimated 3.x. The only change in the crashing release is the
upgrade to RN 0.85.1 + Reanimated 4.3.0 + worklets 0.8.1.
Steps to reproduce
No deterministic repro; the crash is aggregated from production
telemetry. Given the "Early crashes" tag and the observed pattern
(main thread inside AroundLock + JS thread waiting on the same lock),
the trigger is likely a rapid surface mount/unmount early in app
start (e.g. navigation transition or reanimated-heavy component
mount) racing with the rAF flush. Reanimated is used transitively via
common libraries (react-native-reanimated-carousel,
react-native-bottom-tabs, @gorhom/bottom-sheet,
react-native-sortables, react-native-screens).
Snack or a link to a repository
Not available - production crash aggregated via Crashlytics, no
minimal repro yet. Filing anyway per the guidance in #6245 that a
clear explanation of the race can still be actionable.
Main-thread stack (symbolicated, app-specific frames removed)
JS thread at time of crash (blocked on same lock)
Reanimated version
4.3.0
Worklets version
0.8.1
React Native version
0.85.1
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native CLI
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
Multiple models (42 distinct users affected); crash is not device-
specific.
Acknowledgements
Yes - searched for similar issues. Closest matches: #9111, #6245,
#7666. Filing a dedicated thread because none of those describe a
reproducible null-deref crash under the 4.3.0 + worklets 0.8.1 + RN
0.85.1 stack, and the crash rate is high enough to warrant tracking
separately.
generated with Claude