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
The macOS NavigationPageRenderer.Init requires NavigationPage.CurrentPage to be non-null before wiring navigation events and the toolbar. CurrentPage is null when the NavigationPage was built without a root page and nothing was pushed before rendering (the parameterless NavigationPage() ctor leaves it null). Without a current page the renderer cannot show anything, so it throws InvalidOperationException. This is the macOS counterpart of the GTK error 104.
Source
Thrown at src/Compatibility/Core/src/MacOS/Renderers/NavigationPageRenderer.cs:204
{
var removed = await PopPageAsync(page, animated);
Platform.NativeToolbarTracker.UpdateToolBar();
return removed;
}
protected virtual async Task<bool> OnPush(Page page, bool animated)
{
var shown = await AddPage(page, animated);
Platform.NativeToolbarTracker.UpdateToolBar();
return shown;
}
void Init()
{
ConfigurePageRenderer();
if (NavigationPage.CurrentPage == 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.");
Platform.NativeToolbarTracker.Navigation = NavigationPage;
NavigationPage.PushRequested += OnPushRequested;
NavigationPage.PopRequested += OnPopRequested;
NavigationPage.PopToRootRequested += OnPopToRootRequested;
NavigationPage.RemovePageRequested += OnRemovedPageRequested;
NavigationPage.InsertPageBeforeRequested += OnInsertPageBeforeRequested;
NavigationPage.Popped += OnPopped;
NavigationPage.PoppedToRoot += OnPoppedToRoot;
UpdateBarBackgroundColor();
UpdateBarBackground();
UpdateBarTextColor();
_events = new EventTracker(this);
_events.LoadEvents(NativeView);View on GitHub (pinned to f377ff1c5e)
Solutions
- Pass a root page to the constructor: var nav = new NavigationPage(new ContentPage()); MainPage = nav;
- If using the parameterless ctor, PushAsync the root before the page is rendered (before MainPage assignment).
- Ensure custom NavigationPage subclasses always set a root before becoming visible.
Example fix
// before var nav = new NavigationPage(); MainPage = nav; // throws: CurrentPage null // after var nav = new NavigationPage(new HomePage()); MainPage = nav;
Defensive patterns
Strategy: validation
Validate before calling
var nav = new NavigationPage();
if (nav.CurrentPage == null)
await nav.PushAsync(new ContentPage());
MainPage = nav; Type guard
static bool HasRoot(NavigationPage np) => np.CurrentPage != null;
Prevention
- Prefer the NavigationPage(Page root) constructor.
- Push a root before assigning a parameterless NavigationPage to MainPage.
- Test that MainPage is a NavigationPage with a non-null CurrentPage.
When it happens
Trigger: Constructing new NavigationPage() (no root) and then rendering it (assigning to MainPage) before any PushAsync. NavigationPage.CurrentPage == null at renderer Init time.
Common situations: Parameterless NavigationPage() used with intent to push later, but rendered immediately. Refactor that moved the first PushAsync after MainPage assignment. Subclass that defers root creation.
Related errors
- NavigationPage must have a root Page before being used. Eith
- call Forms.Init() before this
- application
- PopAsync is not supported globally on macOS, please use a Na
- PopToRootAsync is not supported globally on macOS, please us
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/9f695ddeb0f31520.
Report an issue: GitHub.