Skip to content

[Android] Modal TabbedPage whose tabs are NavigationPage(ContentPage) is retained after PopModalAsync() #33918

Description

@brunck

Description

On Android, a modal navigation flow that pushes a TabbedPage (via INavigation.PushModalAsync) leaks after it is popped when each tab is wrapped in its own NavigationPage. After PopModalAsync(), forcing a full GC (GC.Collect() + GC.WaitForPendingFinalizers() + GC.Collect()) does not reclaim the modal TabbedPage or its tab pages.

This can lead to unbounded memory growth in apps that repeatedly open/close modal tabbed workflows (a common pattern). This repro uses standard MAUI Navigation only (no Shell).

See the repro README for more information.

Steps to Reproduce

  • Deploy/run the reproduction app on Android.

  • On the main screen:
    Ensure Wrap tabs in NavigationPage is ON (default).
    Leave Iterations at the default (5), or set to any value > 1.

  • Tap Run repro N times.

  • Observe the Status output after each iteration. The app:
    Pushes a modal TabbedPage.
    Switches to the Settings tab.
    Pops the modal TabbedPage.
    Forces a full GC and updates Status with a “snapshot” line like:
    after pop i/N | Alive=x/y | Types=...

  • Optional: Tap Force GC (before / after) to capture and display snapshots without running the full loop (useful to demonstrate that a forced GC does not reduce the alive counts once the leak has occurred).

  • Optional: Tap Clear tracked refs to reset the in-app WeakReference tracking before re-running.

Expected Behavior

After await Navigation.PopModalAsync() completes and there are no remaining app references, the popped modal TabbedPage and its child pages should become eligible for collection and should be reclaimed by a forced full GC.

In the repro app, after each pop + forced GC, the tracked objects’ “Alive” count should return to 0 (or remain stable and not increase across iterations).

Actual Behavior

On Android, after each modal pop and forced full GC:

The popped modal TabbedPage remains alive.
The tab children remain alive (the per-tab NavigationPage wrappers).
The inner ContentPage inside each NavigationPage remains alive.
In the repro app, the Status output continues to show non-zero “Alive” counts after GC, and the alive counts increase as the loop repeats.

Link to public reproduction project repository

https://github.com/brunck/reproductions/tree/master/MauiTabbedModalLeakRepro

Version with bug

10.0.31

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android

Affected platform versions

Android 16 - API 36

Did you find any workaround?

Could not find a workaround.

Activity

  1. TamilarasanSF4853 commented on Feb 6, 2026

    @TamilarasanSF4853
    Contributor

    This issue has been validated in Visual Studio Code 1.109.0 with MAUI versions 9.0.120, 10.0.0 and 10.0.31. It can be reproduced in .NET 10 on the Android platform.
    Note: The issue is not reproduced in the .NET 9 MAUI version 9.0.120.

    net10.mov
    net9.mov
  2. added
    s/verifiedVerified / Reproducible Issue ready for Engineering Triage
    s/triagedIssue has been reviewed
    i/regressionThis issue described a confirmed regression on a currently supported version
    on Feb 6, 2026
  3. added this to the .NET 10 SR5 milestone on Feb 10, 2026
  4. added a commit that references this issue on Feb 24, 2026
    70760ec
  5. added a commit that references this issue on Feb 24, 2026
    5d258c7
  6. added 2 commits that reference this issue on Mar 2, 2026
    d7168eb
    69c9bda
  7. added a commit that references this issue on Mar 3, 2026
    de6523f
  8. added a commit that references this issue on Mar 5, 2026
    ab665a0
  9. added a commit that references this issue on Mar 6, 2026
    ad9b09a
  10. added a commit that references this issue on Mar 11, 2026
    3a6081d
  11. locked and limited conversation to collaborators on Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    i/regressionThis issue described a confirmed regression on a currently supported versionpartner/syncfusionIssues / PR's with Syncfusion collaborationregressed-in-10.0.0s/triagedIssue has been revieweds/verifiedVerified / Reproducible Issue ready for Engineering Triaget/bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions