dotnet/maui · critical · NotSupportedException

Popped page does not appear on top of current navigation sta

Error message

Popped page does not appear on top of current navigation stack, please file a bug.

What it means

OnPopViewAsync verifies that the page being popped matches the Child of the current TopViewController (a ParentingViewController). If they differ, the platform's notion of the top of the stack disagrees with the MAUI logical stack - a state corruption. It throws NotSupportedException asking the user to file a bug because this is an unexpected internal-state mismatch.

Source

Thrown at src/Compatibility/Core/src/iOS/Renderers/NavigationRenderer.cs:336

			_ignorePopCall = false;
			var success = !await task;

			UpdateToolBarVisible();
			return success;
		}

		protected virtual async Task<bool> OnPopViewAsync(Page page, bool animated)
		{
			if (_ignorePopCall)
				return true;

			var renderer = Platform.GetRenderer(page);
			if (renderer == null || renderer.ViewController == null)
				return false;

			if (page != ((ParentingViewController)TopViewController).Child)
				throw new NotSupportedException("Popped page does not appear on top of current navigation stack, please file a bug.");

			var task = GetAppearedOrDisappearedTask(page);

			UIViewController poppedViewController;
			_ignorePopCall = true;
			poppedViewController = base.PopViewController(animated);

			var actuallyRemoved = poppedViewController == null ? true : !await task;
			_ignorePopCall = false;

			poppedViewController?.Dispose();

			UpdateToolBarVisible();
			return actuallyRemoved;
		}

		protected virtual async Task<bool> OnPushAsync(Page page, bool animated)
		{

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Avoid mixing NavigationPage.PushAsync/PopAsync with direct UINavigationController calls.
  2. Serialise navigation operations (await each Push/Pop) to prevent overlapping mutations.
  3. Ensure RemovePage/InsertPageBefore are not called while a Pop is in flight.
  4. If reproducible, report with the exact navigation sequence and MAUI version.

Example fix

// before (concurrent navigation)
_ = Navigation.PopAsync();
Navigation.InsertPageBefore(other, current);

// after (serialised)
await Navigation.PopAsync();
Navigation.InsertPageBefore(other, current);
Defensive patterns

Strategy: try-catch

Try / catch

try { await Navigation.PopAsync(animated); }
catch (NotSupportedException ex) when (ex.Message.Contains("navigation stack"))
{
    // stack desync - resync by reading Navigation.NavigationStack
    // and avoid concurrent navigation
}

Prevention

When it happens

Trigger: A PopAsync/PopAsync(page) call where the requested page is not actually the top of the iOS view-controller stack; concurrent/mismatched Push/Pop/InsertPageBefore/RemovePage calls; manually calling base.PopViewController elsewhere; custom navigation that mutates ViewControllers directly.

Common situations: Mixing NavigationPage methods with custom UINavigationController manipulation; calling RemovePage during an in-flight Pop; navigation triggered from multiple threads; handler/renderer version mismatches after an upgrade.

Related errors


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