dotnet/maui · error · InvalidOperationException

This should never happen, please file a bug

Error message

This should never happen, please file a bug

What it means

In InsertPageBefore, the renderer looks up the 'before' page in PageController.InternalChildren (the NavigationPage's own model-level stack). If IndexOf returns -1, the page isn't in the model stack at all — an invariant violation between the model (NavigationPage.InternalChildren) and the call. The message asks for a bug report because the navigation framework should keep these in sync; a user-facing InsertPageBefore(page, nonStackPage) would surface a different error upstream.

Source

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

				{
					Widget.RemoveFromContainer(target.Container);
				}

				FinishRemovePage(page, removeFromStack);
			}
		}

		private void InsertPageBefore(Page page, Page before)
		{
			if (before == null)
				throw new ArgumentNullException(nameof(before));
			if (page == null)
				throw new ArgumentNullException(nameof(page));

			int index = PageController.InternalChildren.IndexOf(before);

			if (index == -1)
				throw new InvalidOperationException("This should never happen, please file a bug");

			var items = _currentStack.ToArray();
			_currentStack.Clear();

			int counter = 0;

			foreach (var item in items.Reverse())
			{
				if (counter == index)
				{
					_currentStack.Push(new NavigationChildPage(page));

					if (Platform.GetRenderer(page) == null)
						Platform.SetRenderer(page, Platform.CreateRenderer(page));
				}

				_currentStack.Push(item);

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Serialize navigation mutations (avoid concurrent Push/Pop/InsertPageBefore on the same NavigationPage) so the model stack stays consistent.
  2. Before calling Navigation.InsertPageBefore(page, before), verify the 'before' page is still on the stack: if (!Navigation.NavigationStack.Contains(before)) return;
  3. If reproducible, file a bug with the navigation sequence as the message requests — this path indicates a framework invariant breach.

Example fix

// before
Navigation.InsertPageBefore(newPage, targetPage); // targetPage may already be popped

// after
if (Navigation.NavigationStack.Contains(targetPage))
    Navigation.InsertPageBefore(newPage, targetPage);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure 'before' is still on the model stack before inserting.
if (Navigation.NavigationStack.Contains(before))
    Navigation.InsertPageBefore(page, before);

Type guard

static bool IsOnStack(Page p) => Navigation.NavigationStack.Contains(p);

Try / catch

try { Navigation.InsertPageBefore(page, before); }
catch (InvalidOperationException ex) when (ex.Message.Contains("never happen"))
{ /* log + skip; indicates stack desync */ }

Prevention

When it happens

Trigger: NavigationPage's renderer receives an InsertPageBefore request whose 'before' page is not present in the NavigationPage's InternalChildren. This usually reflects an internal desync rather than a direct API misuse, often triggered by rapid/reentrant navigation or a push/pop race on GTK.

Common situations: Programmatic navigation fired while a previous navigation animation/completion is still in flight. Custom navigation logic that calls InsertPageBefore with a page that was already removed. Shell or custom routers interacting with a NavigationPage on GTK.

Related errors


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