Crashes with the error: java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference in method 'void android.view.ViewGroup.dispatchGetDisplayList()'
Description
I customized a Modal component using the Animated.View component with entering and exiting props. When the Modal closes and navigates to another screen, the app crashes with the error: java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference in method 'void android.view.ViewGroup.dispatchGetDisplayList()'. I tried removing the exiting prop, and the crash didn't happen. Not all devices crash—most crashes are related to Oppo/Realme, etc.
Steps to reproduce
- create a project with expo (npx create-expo-app@latest)
- reset project (npm run reset-project)
- install dependency (npx expo install ahooks react-native-get-random-values uuid react-native-keyboard-controller react-native-paper)
- prebuild (expo prebuild)
- add two screen (index and test)
- add Modal component
- add a button to open a drawer on index screen
- navigate to test screen on Modal callback "onConfirm"
- build a release app and install to a device (oppo or realme)
- open the app in default index screen, click the button to open the drawer and then click the action
- the screen change to test screen and then the app crash
Snack or a link to a repository
https://github.com/rpyoyo/crash-reproduction-react-native-reanimated.git
Reanimated version
4.1.3
Worklets version
0.6.1
React Native version
0.81.4
Platforms
Android
JavaScript runtime
Hermes
Workflow
Expo Dev Client
Architecture
New Architecture (Fabric renderer)
Build type
Release app & production bundle
Device
Real device
Host machine
Windows
Device model
Realme GT Neo (RMX3350) Android 13
Acknowledgements
Yes
By the way, the same code works fine with expo@53 and [email protected]. I just upgraded the Expo version to 54, and the related react-native-reanimated was forced to upgrade to 4.1.3.
hi @rpyoyo, thanks for opening the issue! Could you add reproduction code? Unfortunately we can't do much without it, thanks
hi @rpyoyo, thanks for opening the issue! Could you add reproduction code? Unfortunately we can't do much without it, thanks
I just created a minimal reproduction repo.
With the app built by this repo, I found that on a Realme GT Neo (RMX3350) device running Android 11, it works normally, but crashes on another Realme GT Neo (RMX3350) device running Android 13.
Here is a video record test on OPPO Reno6 5G running Android 13.
https://github.com/user-attachments/assets/123d211d-e622-4efc-a8c3-592a135e8ffc
I have exactly same problem, problem occurs in production build (dev is fine, but not always)
Same issue — it’s critical and affects all our users on Chinese devices (OPPO, Huawei, etc.). It occurs when performing an exit animation during navigation using @react-navigation/native-stack. I’ve detailed my findings here as well: https://github.com/GSTJ/react-native-magic-modal/issues/155. I think this is a react-native-reanimated issue as when I make the exit animations duration of 1 millisecond, it doesn't happen as often.
Same issue. I am using a Realme Device (Realme 14 5g). For me, it occurs when navigating away from the screen that has a reanimated component with exiting and layout animation. Specifically, it crashes when navigating away from the screen while it is still animating (exiting/layout animations).
package.json:
"expo": "~54.0.13", "react-native-reanimated": "~4.1.2", "react-native-worklets": "^0.5.1", "react-native-gesture-handler": "~2.28.0",
I was able to reproduce the crash using provided repro https://github.com/rpyoyo/crash-reproduction-react-native-reanimated on a Realme GT2 with the following stacktrace:
FATAL EXCEPTION: main
Process: com.rpyoyo.test, PID: 20027
java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference in method 'void android.view.ViewGroup.dispatchGetDisplayList()'
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4561)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4589)
at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4562)
at android.view.View.updateDisplayListIfDirty(View.java:22213)
at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:682)
at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:688)
at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:790)
at android.view.ViewRootImpl.draw(ViewRootImpl.java:4842)
at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4537)
at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3723)
at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2442)
at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:9375)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1388)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1396)
at android.view.Choreographer.doCallbacks(Choreographer.java:1033)
at android.view.ChoreographerExtImpl.checkScrollOptSceneEnable(ChoreographerExtImpl.java:408)
at android.view.Choreographer.doFrame(Choreographer.java:900)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1371)
at android.os.Handler.handleCallback(Handler.java:942)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:240)
at android.os.Looper.loop(Looper.java:351)
at android.app.ActivityThread.main(ActivityThread.java:8355)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:584)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1013)
I am working on this in parallel as this is impacting a client of ours.
Sharing my findings & understanding:
-
The problem only happens when using react-native-screens / native-stack
-
The issue is that the view hierarchy is modified while we are drawing (which we always have to avoid on android)
-
RNS dispatches progress updates here: https://github.com/software-mansion/react-native-screens/blob/1443bd9e95618839b3b9687f81a4833598b35372/android/src/main/java/com/swmansion/rnscreens/stack/anim/ScreensAnimation.kt#L16
-
This will be intercepted by REAs NodeManager, which will call
performOperations: https://github.com/software-mansion/react-native-reanimated/blob/3380da1e8ecb4f2f38763db207d918b76cc9e72b/packages/react-native-reanimated/android/src/main/java/com/swmansion/reanimated/NodesManager.java#L190-L192 -
performOperationswill sync execute a render transaction here (which was introduced here): https://github.com/software-mansion/react-native-reanimated/blob/3380da1e8ecb4f2f38763db207d918b76cc9e72b/packages/react-native-reanimated/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp#L654-L663 -
This will eventually cause to change the layout / view hierarchy while we are drawing, which causes the crash
-
(I think in this case it even might even starts to sync execute the commit that react was scheduling async as we are using
notifyDelegatesOfUpdates, which is just using the ShadowTree's latest mountingCoordinator)
Things that work around the issue:
- Reverting https://github.com/software-mansion/react-native-reanimated/pull/7798/ fixes the crash from the reproduction provided
- Commenting out the progress updates here fixes the issue: https://github.com/software-mansion/react-native-screens/blob/1443bd9e95618839b3b9687f81a4833598b35372/android/src/main/java/com/swmansion/rnscreens/stack/anim/ScreensAnimation.kt#L16
Now, the thing is, I am seeing this crash on REA 3.17.1 as well, so i don't think its necessarily this specific change that causes the issue.
The problem here is much rather that we dispatch the event in RNS onAnimationEnd, which gets triggered as part of the drawing cycle.
Reanimated at this point could have work to process, or not, which would also explain why i can't reproduce the crash reliably in our client's app.
To fix this I think we could:
a) make sure RNS doesn't dispatch the event directly on animation draw but use like post to put in the queue
b) make sure we don't perform a mount sync when we are drawing at the moment
c) something else i haven't thought of yet
Stack of RNS causing dispatching of event during draw:
btw, i really think we should land the change that we only sync process events in REA if there is a registered handler for it, also for performance reasons
-> Going to open an issue & PR in RNS
Potential PR is up here:
- https://github.com/software-mansion/react-native-screens/pull/3322
@hannojg Thanks for your investigation!
I've consulted this issue with @bartlomiejbloniarz who authored the PR https://github.com/software-mansion/react-native-reanimated/pull/7798 which you have mentioned. He suggested that we might want to skip flushing layout animations in case of handling an event.
We drafted the following patch that adds a boolean flag to performOperations: react-native-reanimated+4.1.3.patch After applying the patch in the repro project we're no longer able to reproduce the crash.
Can you please try the following patch and let us know if it fixes the bug?
I am pretty sure that this would fix the issue in this particular case 👍
However, i think there are other cases where a crash could still happen. That is, if:
- on the JS side we start queueing operations to reanimated
- we dispatch the transitionProgress event in RNS (during drawing as is now)
- with your patch reanimated now skips over the first sync render, cool 👍
- however, further down in
performOperationswe will have items in the update queue to process - we make a sync commit to the shadow tree which will lead to a sync mount, which will lead to the same crash
So I think we should reconsider how this can be solved more holistically? Ie. i think by the fix i proposed in RNS we completely avoid this problem - but maybe i am missing something 🤔
I am getting a similar crash when a layout exit animation runs for a toast while scrolling a flatlist (old arch)
Thanks @tomekzaw, the patch you provided indeed solves the issue. Here’s a patch to apply to react-native-screens+4.16.0.patch, including the changes made by @hannojg, which also fixes the problem on the other side. However, I think I’ll go with @tomekzaw’s approach, since it seems to be the correct behavior.
For those who want to use the patch provided by @tomekzaw, in addition to working on iOS, you should also include this in the patch:
diff --git a/node_modules/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm b/node_modules/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm
index 793d28d..19a4e2d 100644
--- a/node_modules/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm
+++ b/node_modules/react-native-reanimated/apple/reanimated/apple/native/NativeProxy.mm
@@ -46,7 +46,7 @@ std::shared_ptr<ReanimatedModuleProxy> createReanimatedModuleProxy(
std::weak_ptr<ReanimatedModuleProxy> weakReanimatedModuleProxy = reanimatedModuleProxy; // to avoid retain cycle
[nodesManager registerPerformOperations:^() {
if (auto reanimatedModuleProxy = weakReanimatedModuleProxy.lock()) {
- reanimatedModuleProxy->performOperations();
+ reanimatedModuleProxy->performOperations(false);
}
}];
this also happens on latest version 3, just a heads up.
@RodolfoSilva Thanks for testing out the patch as well as expanding it for iOS.
I've submitted a PR based on the patch from https://github.com/software-mansion/react-native-reanimated/issues/8422#issuecomment-3431590258 and https://github.com/software-mansion/react-native-reanimated/issues/8422#issuecomment-3437310014:
- https://github.com/software-mansion/react-native-reanimated/pull/8459
As for the alternative PR to react-native-screens by @hannojg (https://github.com/software-mansion/react-native-screens/pull/3322) that postpones emitting the event, I've consulted the issue with @kkafar (maintainer of react-native-screens) and he is hesitant to merge the PR because the change could also affect other mechanisms and potentially introduce a one-frame delay between the event and the reaction. He also pointed out that there's no crash without Reanimated (react-native-screens itself doesn't crash) so the issue should be addressed in Reanimated, not Screens.
@hannojg As for the comment https://github.com/software-mansion/react-native-reanimated/issues/8422#issuecomment-3431656855, could you please expand a bit on this? Do you have an idea for a code snippet that would cause a crash even once https://github.com/software-mansion/react-native-reanimated/pull/8459 is merged?
same issue, waiting to merge PR
Hoping to see this PR merged!
I have the same problem, hope to see this merged soon. Thx guys for the amazing work 🧡
I encountered the same problem. Hope it merged soon! 🎉
I'm also seeing the same problem. Should I be cautious about using the patch, as it hasn't passed the review? Is there a reason to be concerned about using it?
Keep up the good work! ❤️
@hannojg Friendly bump on this, what's the exact concern that you have regarding the PR https://github.com/software-mansion/react-native-reanimated/pull/8459? We'd like to merge it and release it as soon as possible.
this also happens on latest version 3, just a heads up.
I can also say that it is happening with version 3 + react-native 0.81 in old arch. Will there be a fix for this in v3 as well?
Hm, i don't have an exact concern with it i am sure that it will fix the issue 👍 Just some thoughts:
- I think back in the days this was added to have animations triggered from gesture handlers to be in perfect sync. So we might get a one frame delay. From internal sources I know that this was a concern to kmagiera back in the days, not sure if it is still nowadays
- I am wondering if we should invest in the proper setup where we only intercept / handle events for events that are backed by a
useEventhook - however that wouldn't really fix the issue here. But maybe inuseEventwe could specify if an event should callperformOperationssync? Then RNGH could opt in to that where RNS would for example opt out (or additionally, if a user isn't even using the ReanimatedScreen, thus not usinguseEventon the transition progress, then we wouldn't even handle that event, thus also fixing the issue for that case) - Performance wise i think this is a good change, many times we turned this off as you did in the PR for clients who's apps showed performance issues due to that 👍
@hannojg Thanks for your response.
- I think back in the days this was added to have animations triggered from gesture handlers to be in perfect sync. So we might get a one frame delay. From internal sources I know that this was a concern to kmagiera back in the days, not sure if it is still nowadays
Yes, having a one frame delay is (and always has been) a concern for us. We always want the gesture-base animations to be in perfect sync and with no delay at all. But it seems like this PR should not affect useAnimatedStyle animations at all because it only skips flushing layout animations in case performOperations is triggered by event. Does this make sense?
- I am wondering if we should invest in the proper setup where we only intercept / handle events for events that are backed by a useEvent hook - however that wouldn't really fix the issue here.
This also makes sense, there's plenty of optimizations we could apply in similar cases. Feel free to share yours as always!
- Performance wise i think this is a good change, many times we turned this off as you did in the PR for clients who's apps showed performance issues due to that 👍
Thanks, good to hear that you've already tested this out in the production!
I think we can finally proceed with merging https://github.com/software-mansion/react-native-reanimated/pull/8459.
@tomekzaw Could we please reopen this issue? We are still experiencing crashes with the latest version, which includes this fix: 4.2.0-nightly-20251109-b10bd9cb3 https://chrono24-gmbh.sentry.io/share/issue/ee6a62892aac4dec989d5bb17e9d29c0/
I'm running into the same issue. This crash is responsible for 71.4% of our crashes on production. Like others I have tried the provided patch but has unfortunately not helped
@Brma1048 @dannyBies Do you have any repro that we could use to investigate this issue?
