duckduckgo / duckduckgo/Android

[Bug] Crash when switching tabs in ViewPager2 due to LayoutTransition conflict

Open
#8,144 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug needs triage
Dominant language
Kotlin
Stars
4.8k
Forks
1.4k
Avg merge
2d 17h
Merged PRs (30d)
170

Description

Describe the bug

The app crashes when switching tabs (ViewPager2 pages) in the browser.

The crash is caused by a ViewGroup using LayoutTransition (or animateLayoutChanges="true"), which conflicts with ViewPager2's internal scrolling animation and results in an IllegalStateException.

This issue occurs during normal UI interaction and is not specific to test frameworks.

How to Reproduce

Steps to reproduce the behavior:

  1. Launch the DuckDuckGo app
  2. Open multiple tabs in the browser
  3. Trigger a tab switch (e.g., via tab manager or programmatic navigation)
  4. Observe crash

I found this crash by automated testing tool.

Logcat shows:

--------- beginning of crash
03-30 01:21:50.933 20810 20810 E AndroidRuntime: FATAL EXCEPTION: main
03-30 01:21:50.933 20810 20810 E AndroidRuntime: Process: com.duckduckgo.mobile.android.debug, PID: 20810
03-30 01:21:50.933 20810 20810 E AndroidRuntime: java.lang.IllegalStateException: Page(s) contain a ViewGroup with a LayoutTransition (or animateLayoutChanges="true"), which interferes with the scrolling animation. Make sure to call getLayoutTransition().setAnimateParentHierarchy(false) on all ViewGroups with a LayoutTransition before an animation is started.
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at androidx.viewpager2.widget.ScrollEventAdapter.updateScrollEventValues(ScrollEventAdapter.java:271)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at androidx.viewpager2.widget.ScrollEventAdapter.getRelativeScrollPosition(ScrollEventAdapter.java:406)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at androidx.viewpager2.widget.ViewPager2.setCurrentItemInternal(ViewPager2.java:654)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at androidx.viewpager2.widget.ViewPager2.setCurrentItem(ViewPager2.java:614)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at com.duckduckgo.app.browser.BrowserActivity.onMoveToTabRequested$lambda$51(BrowserActivity.kt:1470)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at com.duckduckgo.app.browser.BrowserActivity.$r8$lambda$JCC60xI_JcBNHNTavCcUC05kgBA(Unknown Source:0)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at com.duckduckgo.app.browser.BrowserActivity$$ExternalSyntheticLambda5.run(D8$$SyntheticClass:0)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:873)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:99)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at android.os.Looper.loop(Looper.java:193)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:6669)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
03-30 01:21:50.933 20810 20810 E AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
03-30 01:21:51.908 2603 18416 E ActivityThread: Failed to find provider info for com.google.android.apps.gsa.testing.ui.audio.recorded

the action sequence before the crash

action: 9@back
action: 3@click resource-id=com.duckduckgo.mobile.android.debug:id/aiChatIconMenu :android.widget.ImageView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 10@scroll direction=down
action: 3@click className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 2@edit resource-id=com.duckduckgo.mobile.android.debug:id/omnibarTextInput :android.widget.EditText@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 1@click resource-id=com.duckduckgo.mobile.android.debug:id/backIcon :android.widget.ImageView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 3@click className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 9@click className=android.widget.Button,instance=0 :android.widget.Button@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 3@click className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 4@click className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 2@click resource-id=com.duckduckgo.mobile.android.debug:id/duckAIToolbarButton :android.widget.Button@
action: 11@scroll direction=up
action: 4@click resource-id=com.duckduckgo.mobile.android.debug:id/fireIconImageView :android.widget.ImageView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 5@back
action: 3@click className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 5@clickLong className=android.widget.TextView,instance=0 :android.widget.TextView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 16@edit resource-id=com.duckduckgo.mobile.android.debug:id/omnibarTextInput :android.widget.EditText@weather forecast today
action: 1@click resource-id=com.duckduckgo.mobile.android.debug:id/fireIconImageView :android.widget.ImageView@recycler items_com.duckduckgo.app.browser.BrowserActivity_000000000
action: 1@click resource-id=com.duckduckgo.mobile.android.debug:id/leadingIcon :android.widget.ImageView@

Expected behavior

Switching tabs should work smoothly without crashing, regardless of layout animations inside child views.

Environment
- DDG App Version:5.274.0 (debug intern build)
- Device:Android Emulator (medium phone)
- OS: Android 9

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at BrowserActivity.kt:1470 and follow the ViewPager2 tab-switch path shown in the stack trace. Reproduce switching tabs on Android 9 with the listed app version, then identify the child ViewGroup using LayoutTransition or animateLayoutChanges. Done means tab switching no longer raises the reported IllegalStateException.

Written by the indexing model from the issue text.

Assessment

Tech stack
android, kotlin
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.