stride3d/stride · error · ArgumentException

The given source panel is not a root element of this asset.

Error message

The given source panel is not a root element of this asset.

What it means

Thrown by UILibraryRootViewModel.ReplaceRootElement when the sourcePanel's Id is not found among Asset.Asset.Hierarchy.RootParts. Unlike a UIPage, a UI library can have multiple root panels, and this method swaps an existing root panel (identified by index) for a new hierarchy, so the source panel must currently be a root.

Solutions

  1. Pass a panel whose Id matches one of Asset.Asset.Hierarchy.RootParts.
  2. Check Hierarchy.RootParts.Any(x => x.Id == sourcePanel.Id.ObjectId) before calling.
  3. Refresh the view model references after library edits so the panel Ids are current.

Example fix

// before
libraryRoot.ReplaceRootElement(nestedPanel, newHierarchy, targetPanelId);
// after
var root = libraryRoot.Asset.Asset.Hierarchy.RootParts.FirstOrDefault(x => x.Id == nestedPanel.Id.ObjectId);
if (root == null) throw new ArgumentException("Panel is not a root of this library");
libraryRoot.ReplaceRootElement(nestedPanel, newHierarchy, targetPanelId);
Defensive patterns

Strategy: validation

Validate before calling

bool isRoot = libraryRoot.Asset.Asset.Hierarchy.RootParts.Any(x => x.Id == sourcePanel.Id.ObjectId);

Type guard

static bool IsLibraryRoot(UILibraryRootViewModel root, PanelViewModel p) => root.Asset.Asset.Hierarchy.RootParts.Any(x => x.Id == p.Id.ObjectId);

Try / catch

try { libraryRoot.ReplaceRootElement(panel, hierarchy, targetId); } catch (ArgumentException ex) { /* resolve an actual root panel */ }

Prevention

When it happens

Trigger: Calling ReplaceRootElement with a sourcePanel that is a nested (non-root) element of the library, or a panel belonging to another asset, so IndexOf(x => x.Id == sourcePanel.Id.ObjectId) returns -1.

Common situations: Editor drag/drop replacing a child panel instead of a root; stale PanelViewModel references after the library was restructured; passing a UIPage-style single-root assumption into library code.

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

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/UILibraryEditor/ViewModels/UILibraryRootViewModel.cs:34

    public sealed class UILibraryRootViewModel : UIRootViewModel
    {
        public UILibraryRootViewModel(UIEditorBaseViewModel editor, [NotNull] UILibraryViewModel asset, IEnumerable<UIElementDesign> rootElements)
            : base(editor, asset, rootElements)
        {
            NotifyGameSidePartAdded().Forget();
        }

        /// <inheritdoc />
        [NotNull]
        public override string Name { get => "UI Library"; set => throw new NotSupportedException("Can't change the name of a UILibrary object."); }

        /// <inheritdoc />
        public override void ReplaceRootElement(PanelViewModel sourcePanel, AssetCompositeHierarchyData<UIElementDesign, UIElement> hierarchy, Guid targetPanelId)
        {
            if (sourcePanel == null) throw new ArgumentNullException(nameof(sourcePanel));
            var index = Asset.Asset.Hierarchy.RootParts.IndexOf(x => x.Id == sourcePanel.Id.ObjectId);
            if (index < 0)
                throw new ArgumentException(@"The given source panel is not a root element of this asset.", nameof(sourcePanel));

            Asset.AssetHierarchyPropertyGraph.RemovePartFromAsset(sourcePanel.UIElementDesign);
            Asset.AssetHierarchyPropertyGraph.AddPartToAsset(hierarchy.Parts, hierarchy.Parts[targetPanelId], null, index);
        }

        /// <inheritdoc />
        protected override bool CanAddOrInsertChildren(IReadOnlyCollection<object> children, ref string message)
        {
            return true;
        }
    }
}

View on GitHub (pinned to 96fad776d2)