dotnet/maui · error · InvalidOperationException

PopAsync is not supported globally on Android, please use a

Error message

PopAsync is not supported globally on Android, please use a NavigationPage.

What it means

Thrown by the Platform class's explicit INavigation.PopAsync(bool) implementation. The global Android platform only supports modal navigation; PopAsync (non-modal page pop) requires a NavigationPage. The message guides developers to use NavigationPage for stack-based navigation.

Source

Thrown at src/Compatibility/Core/src/Android/AppCompat/Platform.cs:129

		}

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

		IReadOnlyList<Page> INavigation.ModalStack => _navModel.Modals.ToList();

		IReadOnlyList<Page> INavigation.NavigationStack => new List<Page>();

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

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

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

		Task<Page> INavigation.PopModalAsync(bool animated)
		{
			Page modal = _navModel.PopModal();
			((IPageController)modal).SendDisappearing();
			var source = new TaskCompletionSource<Page>();

			IVisualElementRenderer modalRenderer = GetRenderer(modal);
			if (modalRenderer != null)
			{
				var modalContainer = modalRenderer.View.Parent as ModalContainer;
				if (animated)

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Wrap the root page in a NavigationPage so PopAsync resolves to the NavigationPage's implementation.
  2. Use PopModalAsync for modal dismissal at the platform level.
  3. Guard shared navigation code to check whether the current page is hosted in a NavigationPage before calling PopAsync.

Example fix

// before
await Application.Current.MainPage.Navigation.PopAsync();

// after (ensure NavigationPage root)
Application.Current.MainPage = new NavigationPage(new MainPage());
await NavigationPage.GetNavigationPage(Application.Current.MainPage).PopAsync();
Defensive patterns

Strategy: validation

Validate before calling

// Before PopAsync, confirm a NavigationPage is in the hierarchy.
static NavigationPage GetNavigationPage(Page page)
{
    return page as NavigationPage ?? NavigationPage.GetNavigationPage(page);
}
// Usage:
var np = GetNavigationPage(currentPage);
if (np != null) await np.Navigation.PopAsync();
else await currentPage.Navigation.PopModalAsync();

Type guard

static bool HasNavigationPageHost(Page page) => page is NavigationPage || page?.Navigation is NavigationPage;

Prevention

When it happens

Trigger: Calling await Application.Current.MainPage.Navigation.PopAsync() on Android when MainPage is not a NavigationPage. The platform's Navigation property is returned instead of a NavigationPage's, so the explicit interface implementation throws.

Common situations: Shared navigation code calling PopAsync without a NavigationPage root. Cross-platform code that works on iOS but throws on Android because iOS's platform supports the operation.

Related errors


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