stride3d/stride · error · InvalidOperationException
This operation can only be executed on a child of a panel.
Error message
This operation can only be executed on a child of a panel.
What it means
Thrown by UIElementViewModel.Duplicate when the element's Parent is not a PanelViewModel. Duplication clones the element's sub-hierarchy and expects to re-insert it under a panel parent; with a non-panel (e.g. the root or a non-container parent) there is no valid insertion target.
Solutions
- Duplicate an element that is a child of a panel; for the root, create a new root instead of duplicating.
- Wrap the element in a panel first (or add a panel parent), then duplicate.
- Guard the call: only invoke Duplicate() when vm.Parent is PanelViewModel.
Example fix
// before
rootElementViewModel.Duplicate(); // Parent is not a panel
// after
if (rootElementViewModel.Parent is PanelViewModel panel)
panel.Children.OfType<UIElementViewModel>().First().Duplicate();
else
// create a new root via AddChildren instead of duplicating Defensive patterns
Strategy: type-guard
Validate before calling
bool canDuplicate = elementViewModel?.Parent is PanelViewModel;
Type guard
static bool CanDuplicate(UIElementViewModel vm) => vm?.Parent is PanelViewModel;
Try / catch
try { vm.Duplicate(); } catch (InvalidOperationException ex) { /* disable duplicate for non-panel children */ } Prevention
- Enable the Duplicate command only when Parent is a panel.
- Handle root elements via dedicated create-root flows, not Duplicate.
- After container restructures, refresh parent references before duplicating.
When it happens
Trigger: Calling Duplicate() on a UIElementViewModel whose Parent is null or is not a PanelViewModel — e.g. duplicating the root element of a UIPage/library or an element parented to a non-panel container.
Common situations: Invoking duplicate on the single root element of a UIPage; scripting duplication on root nodes; UI states where the parent container was replaced and is no longer a Panel.
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
- Cannot add a component of type
- Cannot add a same component multiple times. Already set at…
- Changing the panel from a user library type is currently…
- Custom strides is not supported with packed PixelFormats
- Grouping elements into a user library type isn't supported.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/550ccce4a682a4bf.
Report an issue: GitHub.
Appendix: source
Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/UIEditor/ViewModels/UIElementViewModel.cs:144
}
/// <inheritdoc/>
public override void Destroy()
{
nameNodeBinding.Dispose();
propagator.Destroy();
// Remove adorner
Editor.Controller.AdornerService.RemoveAdorner(Id.ObjectId).Forget();
var basePrefabNode = Editor.NodeContainer.GetNode(UIElementDesign)[nameof(UIElementDesign.Base)];
basePrefabNode.ValueChanged -= BaseElementChanged;
base.Destroy();
}
[NotNull]
public UIElementViewModel Duplicate()
{
var parentPanel = Parent as PanelViewModel;
if (parentPanel == null) throw new InvalidOperationException("This operation can only be executed on a child of a panel.");
var subTreeRoot = AssetSideUIElement.Id;
var flags = SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects;
var clonedHierarchy = UIAssetPropertyGraph.CloneSubHierarchies(Asset.Session.AssetNodeContainer, Asset.Asset, subTreeRoot.Yield(), flags, out _);
AssetPartsAnalysis.GenerateNewBaseInstanceIds(clonedHierarchy);
var addedRoot = clonedHierarchy.Parts[clonedHierarchy.RootParts.Single().Id];
// Inside a library, rename the element to avoid having the same name
if (Asset is UILibraryViewModel && !string.IsNullOrEmpty(addedRoot.UIElement.Name))
addedRoot.UIElement.Name = NamingHelper.ComputeNewName(addedRoot.UIElement.Name, Parent.Children, x => x.Name);
Asset.AssetHierarchyPropertyGraph.AddPartToAsset(clonedHierarchy.Parts, addedRoot, parentPanel.AssetSideUIElement, parentPanel.Children.IndexOf(this) + 1);
var cloneId = addedRoot.UIElement.Id;
// The view model should already exist at that point
var partId = new AbsoluteId(Asset.Id, cloneId);
var viewModel = (UIElementViewModel)Editor.FindPartViewModel(partId);
if (viewModel == null) throw new InvalidOperationException($"{nameof(viewModel)} can't be null.");
return viewModel;View on GitHub (pinned to 96fad776d2)