PrismLibrary/Prism · error · NavigationException

NavigationException.RelativeNavigationRequiresNavigationPage

NavigationException.RelativeNavigationRequiresNavigationPage

Error message

NavigationException.RelativeNavigationRequiresNavigationPage

What it means

Relative navigation segments like '../' (remove-page) require the current page to be hosted directly inside a NavigationPage, because 'remove' semantics manipulate the NavigationPage's stack. MvvmHelpers.HasDirectNavigationPageParent(currentPage) returned false, so Prism throws instead of silently mis-navigating.

Solutions

  1. Wrap the page's branch in a NavigationPage so relative '..' segments have a stack to manipulate
  2. Remove the '../' segment and use GoBackAsync or an absolute/relative page path appropriate to the container
  3. Restructure the URI to use navigation modes supported by the actual container (e.g. tab selection or modal navigation)

Example fix

// before
await _navigationService.NavigateAsync("../ViewB"); // currentPage not in a NavigationPage
// after
await _navigationService.GoBackAsync();
await _navigationService.NavigateAsync("ViewB");
Defensive patterns

Strategy: validation

Validate before calling

if (uri.Contains("../") && !MvvmHelpers.HasDirectNavigationPageParent(currentPage))
    throw new InvalidOperationException("'../' requires a NavigationPage parent");

Try / catch

try { await nav.NavigateAsync(uri); }
catch (NavigationException ne) when (ne.Message == NavigationException.RelativeNavigationRequiresNavigationPage) { /* restructure nav */ }

Prevention

When it happens

Trigger: Executing a navigation URI containing '../' (ProcessNavigationForRemovePageSegments) where currentPage has no direct NavigationPage parent — e.g. it is a tab child of a TabbedPage, the app root, or was pushed modally.

Common situations: Using '../SomePage' inside a TabbedPage tab; navigating with remove-segments from a page displayed with useModalNavigation; moving apps from NavigationPage-based layouts to shell/tab layouts while keeping old back-rewrite URIs.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/363e9f3c4baa26e8. Report an issue: GitHub.

Appendix: source

Thrown at src/Maui/Prism.Maui/Navigation/PageNavigationService.cs:543

        else if (currentPage is NavigationPage nav)
        {
            await ProcessNavigationForNavigationPage(nav, nextSegment, segments, parameters, useModalNavigation, pageAnimation);
        }
        else if (currentPage is TabbedPage tabbed)
        {
            await ProcessNavigationForTabbedPage(tabbed, nextSegment, segments, parameters, useModalNavigation, pageAnimation);
        }
        else if (currentPage is FlyoutPage flyout)
        {
            await ProcessNavigationForFlyoutPage(flyout, nextSegment, segments, parameters, useModalNavigation, pageAnimation);
        }
    }

    protected virtual Task ProcessNavigationForRemovePageSegments(Page currentPage, string nextSegment, Queue<string> segments, INavigationParameters parameters, bool? useModalNavigation, bool? animated)
    {
        if (!MvvmHelpers.HasDirectNavigationPageParent(currentPage))
        {
            throw new NavigationException(NavigationException.RelativeNavigationRequiresNavigationPage, currentPage);
        }

        return CanRemoveAndPush(segments)
            ? RemoveAndPush(currentPage, nextSegment, segments, parameters, useModalNavigation, animated)
            : RemoveAndGoBack(currentPage, nextSegment, segments, parameters, useModalNavigation, animated);
    }

    private static bool CanRemoveAndPush(Queue<string> segments)
    {
        return !segments.All(x => x == RemovePageSegment);
    }

    private Task RemoveAndGoBack(Page currentPage, string nextSegment, Queue<string> segments, INavigationParameters parameters, bool? useModalNavigation, bool? animated)
    {
        var pagesToRemove = new List<Page>();

        var currentPageIndex = currentPage.Navigation.NavigationStack.Count;
        if (currentPage.Navigation.NavigationStack.Count > 0)

View on GitHub (pinned to 358118cd64)