dotnet/maui · error · InvalidOperationException

PushAsync is not supported globally on GTK, please use a Nav

Error message

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

What it means

The GTK global Platform does not maintain a non-modal page stack; only modals are tracked. PushAsync would have nowhere to push a page, so it throws InvalidOperationException. Non-modal pushes must go through a NavigationPage whose renderer owns the stack. This mirrors PopToRootAsync and the other global-stack ops on the same class.

Source

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

		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)
		{
			_modals.Add(modal);

			modal.DescendantRemoved += HandleChildRemoved;

			var modalRenderer = GetRenderer(modal);
			if (modalRenderer == null)
			{
				modalRenderer = CreateRenderer(modal);
				SetRenderer(modal, modalRenderer);

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Set MainPage to a NavigationPage and navigate through it: Application.Current.MainPage = new NavigationPage(rootPage); then await page.Navigation.PushAsync(next).
  2. If the intent is modal presentation, use await Navigation.PushModalAsync(page) instead — the global Platform supports modals.
  3. Gate platform-specific navigation: if the runtime is GTK, push modally or ensure a NavigationPage is in the hierarchy before pushing.

Example fix

// before
Application.Current.MainPage = new ContentPage();
await rootPage.Navigation.PushAsync(detailPage); // throws on GTK

// after
Application.Current.MainPage = new NavigationPage(new ContentPage());
await rootPage.Navigation.PushAsync(detailPage);
Defensive patterns

Strategy: validation

Validate before calling

if (Application.Current.MainPage is NavigationPage)
    await page.Navigation.PushAsync(next);
else
    await page.Navigation.PushModalAsync(next); // safe on GTK global Platform

Type guard

static bool HasNavStack() => Application.Current?.MainPage is NavigationPage;

Prevention

When it happens

Trigger: Calling await Navigation.PushAsync(page) where Navigation resolves to the global GTK Platform — i.e. the calling Page's parent is the Application/Platform root rather than a NavigationPage. Common when MainPage is a ContentPage directly.

Common situations: Shared code that calls Navigation.PushAsync unconditionally across all platforms. App structured with a single root ContentPage on GTK. Migrating from iOS/Android where global push works.

Related errors


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