dotnet/maui · error · InvalidOperationException

PopToRootAsync is not supported globally on GTK, please use

Error message

PopToRootAsync is not supported globally on GTK, please use a NavigationPage.

What it means

The GTK global Platform implements INavigation but only manages a modal stack, not a page navigation stack. PopToRootAsync is a stack-level operation, so the global Platform throws rather than silently doing nothing. The intended host for non-modal navigation is a NavigationPage, which carries its own renderer-backed stack (NavigationPageRenderer). This is a hard platform limitation of the GTK backend, not a runtime misconfiguration.

Source

Thrown at src/Compatibility/Core/src/GTK/Platform.cs:218

							page.ShowAll();
						}
					}
				}

				DisposeModelAndChildrenRenderers(modal);
			});

			return Task.FromResult<Page>(modal);
		}

		Task INavigation.PopToRootAsync()
		{
			return ((INavigation)this).PopToRootAsync(true);
		}

		Task INavigation.PopToRootAsync(bool animated)
		{
			throw new InvalidOperationException("PopToRootAsync is not supported globally on GTK, please use a NavigationPage.");
		}

		Task INavigation.PushAsync(Page root)
		{
			return ((INavigation)this).PushAsync(root, true);
		}

		Task INavigation.PushAsync(Page root, bool animated)
		{
			throw new InvalidOperationException("PushAsync is not supported globally on GTK, please use a NavigationPage.");
		}

		Task INavigation.PushModalAsync(Page modal)
		{
			return ((INavigation)this).PushModalAsync(modal, true);
		}

		Task INavigation.PushModalAsync(Page modal, bool animated)

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Wrap your root page in a NavigationPage: Application.Current.MainPage = new NavigationPage(rootPage); then call PopToRootAsync on the NavigationPage, not the global Navigation.
  2. If you need root-level navigation, restructure so the page you navigate from is a child of a NavigationPage, and use that page's Navigation property (which resolves to the NavigationPage).
  3. If you only ever use modals on GTK, switch the call to Navigation.PopModalAsync() and PushModalAsync() which the global Platform does support.

Example fix

// before
Application.Current.MainPage = new ContentPage();
await somePage.Navigation.PopToRootAsync(); // throws on GTK

// after
Application.Current.MainPage = new NavigationPage(new ContentPage());
await somePage.Navigation.PopToRootAsync(); // resolved by NavigationPageRenderer
Defensive patterns

Strategy: validation

Validate before calling

// Before calling PopToRootAsync on GTK, ensure a NavigationPage hosts the page.
bool HasNavigationPageHost(Page p) =>
    p?.Parent is NavigationPage ||
    (p?.Navigation?.NavigationStack?.Count ?? 0) >= 0 && p.Parent is NavigationPage;

if (HasNavigationPageHost(currentPage))
    await currentPage.Navigation.PopToRootAsync();

Type guard

static bool IsNavigationPageRoot(Page root) => root is NavigationPage;

Prevention

When it happens

Trigger: Calling Navigation.PopToRootAsync() (or the bool overload) on a Page whose Navigation property resolves to the global GTK Platform instead of a NavigationPage. Concretely: Application.MainPage is set to a plain ContentPage/CarouselPage/TabbedPage (not a NavigationPage), and code calls await Navigation.PopToRootAsync() on GTK.

Common situations: Porting an app to the GTK backend that worked on iOS/Android where the global host exposes a full stack. Setting MainPage to a bare ContentPage and then calling Navigation methods. Code shared across platforms that assumes global navigation support.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/bd45b13fdb4f8f56. Report an issue: GitHub.