{"record":{"id":"550ccce4a682a4bf","repo":"stride3d/stride","slug":"this-operation-can-only-be-executed-on-a-child-of-a-panel","errorCode":null,"errorMessage":"This operation can only be executed on a child of a panel.","messagePattern":"This operation can only be executed on a child of a panel\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/editor/Stride.Assets.Presentation/AssetEditors/UIEditor/ViewModels/UIElementViewModel.cs","lineNumber":144,"sourceCode":"        }\n\n        /// <inheritdoc/>\n        public override void Destroy()\n        {\n            nameNodeBinding.Dispose();\n            propagator.Destroy();\n            // Remove adorner\n            Editor.Controller.AdornerService.RemoveAdorner(Id.ObjectId).Forget();\n            var basePrefabNode = Editor.NodeContainer.GetNode(UIElementDesign)[nameof(UIElementDesign.Base)];\n            basePrefabNode.ValueChanged -= BaseElementChanged;\n            base.Destroy();\n        }\n\n        [NotNull]\n        public UIElementViewModel Duplicate()\n        {\n            var parentPanel = Parent as PanelViewModel;\n            if (parentPanel == null) throw new InvalidOperationException(\"This operation can only be executed on a child of a panel.\");\n\n            var subTreeRoot = AssetSideUIElement.Id;\n            var flags = SubHierarchyCloneFlags.GenerateNewIdsForIdentifiableObjects;\n            var clonedHierarchy = UIAssetPropertyGraph.CloneSubHierarchies(Asset.Session.AssetNodeContainer, Asset.Asset, subTreeRoot.Yield(), flags, out _);\n            AssetPartsAnalysis.GenerateNewBaseInstanceIds(clonedHierarchy);\n\n            var addedRoot = clonedHierarchy.Parts[clonedHierarchy.RootParts.Single().Id];\n            // Inside a library, rename the element to avoid having the same name\n            if (Asset is UILibraryViewModel && !string.IsNullOrEmpty(addedRoot.UIElement.Name))\n                addedRoot.UIElement.Name = NamingHelper.ComputeNewName(addedRoot.UIElement.Name, Parent.Children, x => x.Name);\n            Asset.AssetHierarchyPropertyGraph.AddPartToAsset(clonedHierarchy.Parts, addedRoot, parentPanel.AssetSideUIElement, parentPanel.Children.IndexOf(this) + 1);\n            var cloneId = addedRoot.UIElement.Id;\n\n            // The view model should already exist at that point\n            var partId = new AbsoluteId(Asset.Id, cloneId);\n            var viewModel = (UIElementViewModel)Editor.FindPartViewModel(partId);\n            if (viewModel == null) throw new InvalidOperationException($\"{nameof(viewModel)} can't be null.\");\n            return viewModel;","sourceCodeStart":126,"sourceCodeEnd":162,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/editor/Stride.Assets.Presentation/AssetEditors/UIEditor/ViewModels/UIElementViewModel.cs#L126-L162","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nrootElementViewModel.Duplicate(); // Parent is not a panel\n// after\nif (rootElementViewModel.Parent is PanelViewModel panel)\n    panel.Children.OfType<UIElementViewModel>().First().Duplicate();\nelse\n    // create a new root via AddChildren instead of duplicating","handlingStrategy":"type-guard","validationCode":"bool canDuplicate = elementViewModel?.Parent is PanelViewModel;","typeGuard":"static bool CanDuplicate(UIElementViewModel vm) => vm?.Parent is PanelViewModel;","tryCatchPattern":"try { vm.Duplicate(); } catch (InvalidOperationException ex) { /* disable duplicate for non-panel children */ }","preventionTips":["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."],"tags":["stride","ui-editor","invalid-parent","duplicate"],"backgroundTag":"invalid-state-transition","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}