dotnet/maui · error · InvalidOperationException

No Modal pages found in the stack, make sure you pushed a mo

Error message

No Modal pages found in the stack, make sure you pushed a modal page

What it means

ModalPageTracker.PopAsync takes the last modal from _modals; if the list is empty it throws InvalidOperationException. Pop on a modal stack that was never pushed means there is no modal to dismiss, so rather than returning null it fails fast. This guards the caller from a silent no-op that would break awaiting code.

Source

Thrown at src/Compatibility/Core/src/MacOS/ModalPageTracker.cs:38

			_renderer.View.WantsLayer = true;
			_modals = new List<Page>();
		}

		public List<Page> ModalStack => _modals;

		public Task PushAsync(Page modal, bool animated)
		{
			_modals.Add(modal);
			modal.DescendantRemoved += HandleChildRemoved;
			Platform.NativeToolbarTracker.TryHide(modal as NavigationPage);
			return PresentModalAsync(modal, animated);
		}

		public Task<Page> PopAsync(bool animated)
		{
			var modal = _modals.LastOrDefault();
			if (modal == null)
				throw new InvalidOperationException("No Modal pages found in the stack, make sure you pushed a modal page");
			_modals.Remove(modal);
			modal.DescendantRemoved -= HandleChildRemoved;
			return HideModalAsync(modal, animated);
		}

		internal void LayoutSubviews()
		{
			if (_renderer == null || _renderer.View == null)
				return;

			foreach (var modal in _modals)
			{
				var modalRenderer = Platform.GetRenderer(modal);
				if (modalRenderer != null)
					modalRenderer.SetElementSize(new Size(_renderer.View.Bounds.Width, _renderer.View.Bounds.Height));
			}
		}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Guard the call: if (Navigation.ModalStack.Count > 0) await Navigation.PopModalAsync();
  2. Track whether a modal was pushed before attempting to pop it.
  3. Ensure close handlers are not double-invoked (unsubscribe after first pop).

Example fix

// before
await Navigation.PopModalAsync(); // throws if stack empty

// after
if (Navigation.ModalStack.Count > 0)
    await Navigation.PopModalAsync();
Defensive patterns

Strategy: validation

Validate before calling

if (Navigation.ModalStack.Count > 0)
    await Navigation.PopModalAsync();

Type guard

static bool HasModal() => Navigation.ModalStack.Count > 0;

Prevention

When it happens

Trigger: Calling Navigation.PopModalAsync() when no modal has been pushed on macOS (the modal stack is empty). Also reachable if a modal was already popped once and PopModalAsync is called again.

Common situations: Back/close handling that calls PopModalAsync unconditionally. Double-close where the modal is popped by both an event and explicit code. Shared code assuming a modal is on top without checking ModalStack.

Related errors


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