Skip to content

[Android] useAnimatedScrollHandler cause null child at index X when traversal in dispatchGetDisplayList crash #8907

@huextrat

Description

@huextrat

Description

On Android useAnimatedScrollHandler may cause the application to crash when an animation is in progress and the user navigates back.

If we remove useAnimatedScrollHandler to use a standard onScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) there is no more crashes

This seems highly related to #8422 but here at least we have a fairly easy reproduction and I don't know if the source of the issue is the same for everything that has been reported on this issue.


Android 16+ trace is: ReactViewGroup contains null child at index 1 when traversal in dispatchGetDisplayList, the view may have been removed.
Android 15 and below is: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference in method 'void android.view.ViewGroup.dispatchGetDisplayList()'

According to our Sentry, the error does not occur on any Samsung devices running Android 15 or earlier, but from Android 16, the error also occurs on Samsung devices.

Android 15 and below full stack trace
  java.lang.NullPointerException: Attempt to read from field 'int android.view.View.mViewFlags' on a null object reference
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4593)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4621)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4594)
    at android.view.View.updateDisplayListIfDirty(View.java:20817)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:583)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:589)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:667)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:4317)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:4125)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:3385)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:2166)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:8887)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1280)
    at android.view.Choreographer.doCallbacks(Choreographer.java:1019)
    at android.view.Choreographer.doFrame(Choreographer.java:911)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1248)
    at android.os.Handler.handleCallback(Handler.java:900)
    at android.os.Handler.dispatchMessage(Handler.java:103)
    at android.os.Looper.loop(Looper.java:219)
    at android.app.ActivityThread.main(ActivityThread.java:8668)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1109)
Android 16 full stack trace
java.lang.IllegalStateException: ReactViewGroup contains null child at index 1 when traversal in dispatchGetDisplayList, the view may have been removed.
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4761)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:4794)
    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:4766)
    at android.view.View.updateDisplayListIfDirty(View.java:25119)
    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:694)
    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:700)
    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:798)
    at android.view.ViewRootImpl.draw(ViewRootImpl.java:7016)
    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:6632)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:5531)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:3924)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:12903)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1901)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1910)
    at android.view.Choreographer.doCallbacks(Choreographer.java:1367)
    at android.view.Choreographer.doFrame(Choreographer.java:1292)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1870)
    at android.os.Handler.handleCallback(Handler.java:995)
    at android.os.Handler.dispatchMessage(Handler.java:103)
    at android.os.Looper.loopOnce(Looper.java:273)
    at android.os.Looper.loop(Looper.java:363)
    at android.app.ActivityThread.main(ActivityThread.java:10060)
    at java.lang.reflect.Method.invoke(Method.java)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:632)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:975)

Steps to reproduce

  1. Launch the project on Android (video below is from Pixel 8 Pro, Android API 36.1)
  2. Click on "Open Animated Scroll List"
  3. Scroll through the list and go back while scrolling (= while animation is running)
  4. If there is no crash, repeat the same operation after a certain amount of time and you will be able to reproduce the crash

Snack or a link to a repository

https://github.com/huextrat/repro-android-animatedscrollhandler

Reanimated version

4.2.1

Worklets version

0.7.2

React Native version

0.81.5

Platforms

Android

JavaScript runtime

None

Workflow

None

Architecture

New Architecture (Fabric renderer)

Reanimated feature flags

None

React Native release level

None

Build type

No response

Device

No response

Host machine

None

Device model

No response

Acknowledgements

Yes

Metadata

Metadata

Assignees

No one assigned

    Labels

    Platform: AndroidThis issue is specific to AndroidRepro providedA reproduction with a snippet of code, snack or repo is provided

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions