rAF performOperations → cloneShadowTreeWithNewProps use-after-free (EXC_BAD_ACCESS) on New Arch iOS — regression, not fixed by 4.3.1, no fix through 4.6.0
Description
Regression: the rAF performOperations → shadow-tree-clone use-after-free was NOT fully fixed by 4.3.1 (#9321 / #9323), and there is no fix in the release notes through 4.6.0.
We hit a recurring EXC_BAD_ACCESS (SIGSEGV) in production on the New Architecture (iOS). The corruption happens while hashing folly::dynamic props during a shadow-node clone that Reanimated performs off the requestAnimationFrame batch:
Top frames (Thread 0, crashed) — corruption during the clone:
0 ReactNativeDependencies folly::dynamic::hash
1 ReactNativeDependencies std::__1::__hash_table<…>::__emplace_unique_key_args<…>
3 ReactNativeDependencies std::__1::unordered_map<…>::unordered_map
4 ReactNativeDependencies folly::dynamic::dynamic
5 React facebook::react::ShadowNode::clone
6 Tonie-App reanimated::cloneShadowTreeWithNewPropsRecursive (ShadowTreeCloner.cpp:55)
7…28 Tonie-App reanimated::cloneShadowTreeWithNewPropsRecursive (ShadowTreeCloner.cpp:51) [~24 recursive frames]
30 Tonie-App reanimated::cloneShadowTreeWithNewProps (ShadowTreeCloner.cpp:89)
31 Tonie-App (lambda) ReanimatedModuleProxy.cpp:1079
36 React facebook::react::ShadowTree::tryCommit
37 React facebook::react::ShadowTree::commit
38 Tonie-App reanimated::ReanimatedModuleProxy::commitUpdates (ReanimatedModuleProxy.cpp:1073)
43 React facebook::react::ShadowTreeRegistry::visit
44 Tonie-App reanimated::ReanimatedModuleProxy::commitUpdates (ReanimatedModuleProxy.cpp:1072)
45 Tonie-App reanimated::ReanimatedModuleProxy::performOperations (ReanimatedModuleProxy.cpp:810)Trigger path (bottom frames) — the requestAnimationFrame flush, not a screen transition:
72 Tonie-App worklets::WorkletRuntime::runSync<…>
73 Tonie-App worklets::AnimationFrameBatchinator::flush (AnimationFrameBatchinator.cpp:49)
80 Tonie-App -[AnimationFrameQueue executeQueue:]
81 Tonie-App -[AnimationFrameQueue executeQueueForProMotion:]
82 QuartzCore (CADisplayLink)Why this is a fresh signal
- Same underlying use-after-free as #9293 (closed) and #9303 (closed as dup) — the rAF variant — and matches the long-standing signature in #7666 (open). It is not the screen-pop variant of #9402 (open).
- Those earlier reports were on 4.3.0 / worklets 0.8.x. This one reproduces on 4.5.3 / worklets 0.11.1, i.e. after the 4.3.1 registry-locking fixes (#9321, #9323) that resolved the
AnimatedPropsRegistry::update(scroll) variant — so the rAFperformOperations→ shadow-tree clone variant is not fully resolved. - Still unfixed as of 4.6.0. We reviewed release notes for 4.5.4, 4.5.5, and 4.6.0 — none touch this Fabric path. The one
performOperationsfix (#10229, "guard against nil_performOperationsblock inREANodesManager") is in the legacy PaperREANodesManager, not the FabricReanimatedModuleProxypath in this stack. - The clone recurses ~24 levels, i.e. a deeply nested animated subtree committed off the rAF batch. Corruption in
folly::dynamic::hashduringShadowNode::cloneis consistent with props/shadow nodes being freed or mutated concurrently with the reanimated commit.
What we can provide
- Full symbolicated
.crash(attached). - Sentry event link, frequency, and device/OS distribution on request.
- Confirmation that
USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITSis enabled.
What we don't have
- A minimal deterministic reproduction — it's an intermittent production data-race (~0.2–1% of mounts of the affected screen). The linked repo reconstructs the render shape but does not crash on demand.
Ask
- Is the rAF
performOperationsclone path expected to be covered by the 4.3.1 fixes, or is this a known-remaining variant? - Any instrumentation guidance to capture a deterministic repro (which registry/commit assertions to enable in a debug build), or a recommended config to mitigate on 4.5.x/4.6.x in the meantime?
Steps to reproduce
This is an intermittent production race and does not reproduce deterministically. We isolated the affected screen from Sentry breadcrumbs across 500 crash events:
- 291 / 500 (58%) crashed with the last navigation breadcrumb on our HomeScreen; the next-largest bucket (159, "unknown") crashed before a navigation breadcrumb was recorded, i.e. during app-start / first render. Every other screen is single-to-low-double digits.
- In the affected events the whole breadcrumb trail spans ~200 ms (
Navigating to start screen→ login →Navigation to HomeScreen→ crash), so the crash happens on/near HomeScreen mount, not after user interaction. - HomeScreen mounts several nested animated carousels/sliders simultaneously on first render (a Reanimated-driven horizontal product-card carousel plus multiple sliders using layout animations) — the deeply nested (~24-level) animated subtree cloned on the rAF batch.
Best-effort deterministic repro (see linked repo):
- New-Arch (Fabric/Hermes) iOS release build on Reanimated 4.5.3 / worklets 0.11.1.
- On one screen, mount several nested, independently-animated subtrees at once (multiple horizontal carousels each running Reanimated animations on mount).
- Cold-launch straight onto that screen repeatedly. The crash surfaces intermittently during the first-render commit driven by the
requestAnimationFrameflush.
Snack or a link to a repository
https://github.com/saeed4u/reanimated-raf-clone-repro
Reanimated version
4.5.3
Worklets version
0.11.1
React Native version
0.85.3
Platforms
iOS
JavaScript runtime
Hermes
Workflow
Expo Dev Client
Architecture
New Architecture (Fabric renderer)
Reanimated feature flags
Yes
React Native release level
Stable
Build type
Release app & production bundle
Device
Real device
Host machine
macOS
Device model
Multiple iOS devices in production, iOS 26.x (e.g. iOS 26.5)
Acknowledgements
Yes
Source: software-mansion/react-native-reanimated