dotnet/maui · error · InvalidOperationException

PushAsync is not supported globally on Windows, please use a

Error message

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

What it means

The Windows Platform class implements INavigation explicitly, but PushAsync throws unconditionally. Global (non-NavigationPage) page-stack navigation is unsupported on WinUI/UWP — only a NavigationPage host provides the navigation stack. The Platform class is the fallback INavigation when MainPage is not a NavigationPage.

Source

Thrown at src/Compatibility/Core/src/Windows/Platform.cs:212

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

		Task<Page> INavigation.PopAsync()
		{
			return ((INavigation)this).PopAsync(true);
		}

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

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

		Task<Page> INavigation.PopAsync(bool animated)
		{
			throw new InvalidOperationException("PopAsync is not supported globally on Windows, please use a NavigationPage.");
		}

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

		void INavigation.RemovePage(Page page)
		{
			throw new InvalidOperationException("RemovePage is not supported globally on Windows, please use a NavigationPage.");
		}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Wrap the root page in a NavigationPage: MainPage = new NavigationPage(new MyContentPage())
  2. Access navigation through the NavigationPage's own Navigation property instead of the global one
  3. Use PushModalAsync which IS supported on the global Platform instance
  4. Abstract navigation behind an interface with platform-specific implementations

Example fix

// before
MainPage = new MyContentPage();
MainPage.Navigation.PushAsync(new DetailPage()); // throws on Windows

// after
MainPage = new NavigationPage(new MyContentPage());
MainPage.Navigation.PushAsync(new DetailPage()); // works
Defensive patterns

Strategy: validation

Validate before calling

// Before calling PushAsync, verify NavigationPage is the host
if (Application.Current.MainPage is NavigationPage navPage)
{
    await navPage.Navigation.PushAsync(newPage);
}
else if (Device.RuntimePlatform == Device.WinUI || Device.RuntimePlatform == Device.UWP)
{
    // Windows requires NavigationPage for stack navigation
    Application.Current.MainPage = new NavigationPage(Application.Current.MainPage);
    await Application.Current.MainPage.Navigation.PushAsync(newPage);
}

Type guard

static bool HasNavigationPageSupport()
{
    return Application.Current.MainPage is NavigationPage;
}

Prevention

When it happens

Trigger: Calling Application.Current.MainPage.Navigation.PushAsync(page) when MainPage is a plain ContentPage, FlyoutPage, or TabbedPage rather than a NavigationPage. The Navigation property resolves to the global Platform INavigation instance, which rejects stack operations.

Common situations: Cross-platform shared code where iOS/Android support global navigation but Windows does not; porting from Xamarin.Forms where this difference was not handled; assuming Navigation works uniformly across platforms.

Related errors


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