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
- Remove or merge the existing root before adding a new one, or replace it via ReplaceRootElement.
- Nest the new element under the existing root instead of adding it as a second root.
- 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
- Check RootParts.Count before adding root elements.
- Use ReplaceRootElement to swap roots rather than adding a second one.
- Nest new elements under the existing root by default.
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
- IsObjectReference returned true for an object that is not…
- parent cannot be null
- Can't change the name of a UIPage object.
- The given source panel does not match the currently set…
- Custom strides is not supported with packed PixelFormats
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)