dotnet/maui · error · InvalidOperationException

NavigationPage must have a root Page before being used. Eith

Error message

NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage.

What it means

Thrown as InvalidOperationException by NavigationPageRenderer.SetElement when the NavigationPage's CurrentPage is null. A NavigationPage must have at least one page (the root) on its internal stack before it can be rendered. This is enforced because the renderer immediately reads Element.CurrentPage to set up the native container.

Source

Thrown at src/Compatibility/Core/src/Windows/NavigationPageRenderer.cs:171

			return new SizeRequest(result);
		}

		UIElement IVisualElementRenderer.GetNativeElement()
		{
			return null;
		}

		public void SetElement(VisualElement element)
		{
			if (element != null && !(element is NavigationPage))
				throw new ArgumentException("Element must be a Page", nameof(element));

			NavigationPage oldElement = Element;
			Element = (NavigationPage)element;

			if (Element != null && Element.CurrentPage is null)
				throw new InvalidOperationException(
					"NavigationPage must have a root Page before being used. Either call PushAsync with a valid Page, or pass a Page to the constructor before usage.");

			if (oldElement is INavigationPageController navigationPageController)
			{
				navigationPageController.PushRequested -= OnPushRequested;
				navigationPageController.PopRequested -= OnPopRequested;
				navigationPageController.PopToRootRequested -= OnPopToRootRequested;
				oldElement.InternalChildren.CollectionChanged -= OnChildrenChanged;
				oldElement.PropertyChanged -= OnElementPropertyChanged;
			}

			if (element != null)
			{
				if (_container == null)
				{
					_container = new PageControl();
					_container.PointerPressed += OnPointerPressed;
					_container.SizeChanged += OnNativeSizeChanged;

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Pass a root Page to the NavigationPage constructor: new NavigationPage(new RootPage()).
  2. Call NavigationPage.PushAsync(rootPage) before the renderer attaches if using the parameterless constructor.
  3. Ensure any data-bound NavigationPage has CurrentPage set before binding completes.

Example fix

// before
var navPage = new NavigationPage(); // no root page
MainPage = navPage; // throws in renderer

// after
var navPage = new NavigationPage(new RootPage());
MainPage = navPage;
Defensive patterns

Strategy: validation

Validate before calling

var navPage = new NavigationPage();
if (navPage.CurrentPage == null)
    navPage.PushAsync(new RootPage());

Prevention

When it happens

Trigger: Creating a NavigationPage with the default constructor (no root page) and then passing it to the renderer, or calling PushAsync after the renderer is already attached but before any page was pushed.

Common situations: Using `new NavigationPage()` without passing a root Page in the constructor, or data-binding a NavigationPage that hasn't had PushAsync called yet.

Related errors


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