dotnet/maui · error · 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

PopPageAsync peeks the top of the renderer's _currentStack and compares the popped Page to that wrapper's Page. A mismatch means the page being popped is not the one on top of the visible stack — a state inconsistency. Like error 105 this is an internal invariant; the message requests a bug report because the framework normally keeps the model and renderer stacks aligned.

Source

Thrown at src/Compatibility/Core/src/GTK/Renderers/NavigationPageRenderer.cs:453

				var pageRenderer = Platform.GetRenderer(item.Page);
				Widget.Add(pageRenderer.Container);

				pageRenderer.Container.SetSizeRequest(
					  Allocation.Width,
					  Allocation.Height);

				pageRenderer.Container.ShowAll();
			}
		}

		private async Task<bool> PopPageAsync(Page page, bool animated)
		{
			if (page == null)
				throw new ArgumentNullException(nameof(page));

			var wrapper = _currentStack.Peek();
			if (page != wrapper.Page)
				throw new NotSupportedException("Popped page does not appear on top of current navigation stack, please file a bug.");

			_currentStack.Pop();
			(page as IPageController)?.SendDisappearing();

			var target = Platform.GetRenderer(page);
			var previousPage = _currentStack.Peek().Page;

			await RemovePageAsync(page, false, animated);

			return true;
		}

		private async Task<bool> PopToRootPageAsync(Page page, bool animated)
		{
			if (page == null)
				throw new ArgumentNullException(nameof(page));

			(page as IPageController)?.SendDisappearing();

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Guard against re-entrant pops: track an in-flight flag and ignore a Pop while another navigation is completing.
  2. Debounce or disable the back control until the awaited PopAsync/PushAsync returns.
  3. If reproducible deterministically, report it as a framework bug with the exact sequence — the stacks should not desync under correct use.

Example fix

// before
async void OnBack() => await Navigation.PopAsync(); // double-tap -> second pop desyncs

// after
bool _navigating;
async void OnBack()
{
    if (_navigating) return;
    _navigating = true;
    try { await Navigation.PopAsync(); }
    finally { _navigating = false; }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Prevent re-entrant pops with a flag.
static bool _popping;
async Task SafePop()
{
    if (_popping) return;
    _popping = true;
    try { await Navigation.PopAsync(); }
    finally { _popping = false; }
}

Try / catch

try { await Navigation.PopAsync(); }
catch (NotSupportedException ex) when (ex.Message.Contains("navigation stack"))
{ /* navigation desync; reset state and skip */ }

Prevention

When it happens

Trigger: A Pop request arrives for a page that is not the current top of the GTK NavigationPageRenderer's stack. Typically caused by overlapping/awaited navigation operations: a second PopPageAsync starts before the first completes, or OnPop fires for a page that was already removed.

Common situations: Double-tapping a back button that triggers two PopAsync calls. Awaiting a Push/Pop and then immediately popping again. Hardware back-key handling that races with programmatic navigation on GTK.

Related errors


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