stride3d/stride · error · InvalidOperationException

A UIPage asset can't have more than one root.

Error message

A UIPage asset can't have more than one root.

What it means

Thrown by UIPageRootViewModel.OnRootUIElementsChanged (CollectionAdd branch) when adding a root element would leave the UIPage with a root-parts count other than 1. A UIPage asset is constrained to exactly one root UI element, so the second addition violates the invariant.

Solutions

  1. Remove or merge the existing root before adding a new one, or replace it via ReplaceRootElement.
  2. Nest the new element under the existing root instead of adding it as a second root.
  3. Validate RootParts.Count == 0 before adding a new root programmatically.

Example fix

// before
pageAsset.Hierarchy.RootParts.Add(newPart); // second root
// after
if (pageAsset.Hierarchy.RootParts.Count > 0)
    pageAsset.Hierarchy.RootParts[0].Children.Add(newPart); // nest instead
else
    pageAsset.Hierarchy.RootParts.Add(newPart);
Defensive patterns

Strategy: validation

Validate before calling

bool canAddRoot = pageAsset.Hierarchy.RootParts.Count == 0;

Type guard

static bool CanAddRoot(UIAssetBase page) => page.Hierarchy.RootParts.Count == 0;

Try / catch

try { editor.AddChildren(newElements, modifiers); } catch (InvalidOperationException ex) { /* nest under existing root instead */ }

Prevention

When it happens

Trigger: Calling AddChildren / adding an element while the page already has a root, making Hierarchy.RootParts.Count != 1 after the add; programmatic insertion of a second root part into RootParts.

Common situations: Dragging a new element onto the page canvas when one already exists; scripted asset manipulation appending extra root parts; import tools creating multiple top-level elements.

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 stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/e15c74f95fa178a5. Report an issue: GitHub.

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/UIPageEditor/ViewModels/UIPageRootViewModel.cs:77

                message = "Empty selection";
                return false;
            }

            if (count == 1)
                return true;

            message = OneRootOnly;
            return false;
        }

        /// <inheritdoc />
        protected override void OnRootUIElementsChanged(ItemChangeEventArgs e)
        {
            switch (e.ChangeType)
            {
                case ContentChangeType.CollectionAdd:
                    if (UIAsset.Hierarchy.RootParts.Count != 1)
                        throw new InvalidOperationException(OneRootOnly);
                    Editor.ActiveRoot = RootElement;
                    break;

                case ContentChangeType.CollectionRemove:
                    if (UIAsset.Hierarchy.RootParts.Count != 0)
                        throw new InvalidOperationException(OneRootOnly);
                    break;
            }
        }

        void IAddChildViewModel.AddChildren(IReadOnlyCollection<object> children, AddChildModifiers modifiers)
        {
            if (children.Count != 1)
                return;

            if (RootElement != null)
            {
                ((IAddChildViewModel)RootElement).AddChildren(children, modifiers);

View on GitHub (pinned to 96fad776d2)