dotnet/wpf · error · InvalidOperationException

SR.Format(SR.WrongNavigateRootElement, bp.ToString())

Error message

SR.Format(SR.WrongNavigateRootElement, bp.ToString())

What it means

When downloaded content arrives, NavigationService.OnContentReady() validates the root element via IsValidRootElement(); if the object is not a valid navigation root (e.g. not a Page, PageFunctionBase, or applicable content type) it throws InvalidOperationException with WrongNavigateRootElement including the object's string. NavigationService can only navigate to recognized root element types.

Solutions

  1. Wrap the content in a Page (or use PageFunction) and navigate to that
  2. Navigate to a XAML file whose root is <Page> rather than a bare control
  3. For object navigation, navigate to a page and supply the object via DataContext or NavigationContext

Example fix

// before
frame.Content = new Grid(); // or Navigate(grid)
// after
var page = new Page { Content = new Grid() };
frame.Navigate(page);
Defensive patterns

Strategy: validation

Validate before calling

bool validRoot = content is Page || content is PageFunctionBase;
if (!validRoot) content = new Page { Content = content };

Type guard

bool IsValidNavRoot(object c) => c is Page or PageFunctionBase;

Try / catch

try { frame.Navigate(content); }
catch (InvalidOperationException ex) when (ex.Message.Contains("root element")) {
    frame.Navigate(new Page { Content = content });
}

Prevention

When it happens

Trigger: Navigating to an object or XAML whose root element is not a valid root (e.g. a raw Panel/Control that isn't a Page, or non-UI object) so OnContentReady fails the IsValidRootElement check.

Common situations: Navigating a Frame directly to a UserControl/Panel instead of a Page; loading loose XAML whose root is a layout control; Navigate(object) with an arbitrary business object without a converter/DataTemplate-based page.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/7e05219e053bbbf4. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Navigation/NavigationService.cs:1102

        /// The callback that happens when the bind product corresponding to a
        /// URI has been created.
        /// </summary>
        /// <param name="contentType">MIME type from which product was created</param>
        /// <param name="bp">Content created.</param>
        /// <param name="bpu">Absolute URI of content, or null</param>
        /// <param name="navState"></param>
        void IContentContainer.OnContentReady(ContentType contentType, Object bp, Uri bpu, Object navState)
        {
            Invariant.Assert(bpu == null || bpu.IsAbsoluteUri, "Content URI must be absolute.");
            if (IsDisposed)
            {
                return;
            }

            // If an invalid root element is passed to Navigation Service, throw exception here.
            if (!IsValidRootElement(bp))
            {
                throw new InvalidOperationException(SR.Format(SR.WrongNavigateRootElement, bp.ToString()));
            }

            /*TODO: Uncomment after new loader design is implemented or sync bind reentrancy is resolved
            Debug.Assert(_navStatus == NavigationStatus.Navigating,
                         "Navigation State Machine is messed up, Expected: " + NavigationStatus.Navigating + "; Current: " + _navStatus);*/

            ResetPendingNavigationState(NavigationStatus.Navigated);

            NavigateInfo navInfo = navState as NavigateInfo;
            NavigationMode navMode = navInfo == null ? NavigationMode.New : navInfo.NavigationMode;

            Debug.Assert(bpu == null ||
                         navInfo == null ||
                         navInfo.Source == null ||
                         IsSameUri(null, navInfo.Source, bpu, false /* withFragment */),
                         "Source in OnContentReady does not match source in NavigateInfo");
            if (bpu == null)
            {

View on GitHub (pinned to 81131a70a4)