stride3d/stride · error · InvalidOperationException

The given parentId does not correspond to any existing part.

Error message

The given parentId does not correspond to any existing part.

What it means

UIEditorController.AddPart throws this InvalidOperationException when the parentId for a new UI part cannot be resolved to an existing game-side UIElement via FindPart. The controller maintains a game-side mirror of the asset hierarchy; attaching a child to an unknown parent would corrupt that mirror, so it fails fast.

Solutions

  1. Verify the parentId exists in the current UI hierarchy before calling AddPart.
  2. Create/register the parent part first so parent-before-child ordering holds.
  3. Re-fetch ids after undo/redo or asset reload; never cache ids across transactions.
  4. Confirm the AbsoluteId's asset id matches the currently loaded UI asset.

Example fix

// before
controller.AddPart(newPart, staleParentId);
// after
var parent = viewModel.TreeRoot.Flatten().FirstOrDefault(e => e.Id == staleParentId);
if (parent != null)
    controller.AddPart(newPart, staleParentId);
Defensive patterns

Strategy: validation

Validate before calling

bool parentExists = viewModel.TreeRoot.Flatten().Any(e => e.Id == parentId);
if (!parentExists) throw new InvalidOperationException($"Parent {parentId} not in hierarchy");

Type guard

UIElementViewModel ResolveParent(AbsoluteId id) => viewModel.TreeRoot.Flatten().FirstOrDefault(e => e.Id == id);

Try / catch

try { controller.AddPart(newPart, parentId); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not correspond to any existing part")) {
    // recreate parent or skip
}

Prevention

When it happens

Trigger: Calling AddPart with a parentId that was never registered, was already removed by a prior RemovePart, belongs to a different asset (AbsoluteId asset-id mismatch), or whose game-side element was not yet created.

Common situations: Editor plugins/scripts reusing stale ids after undo/redo, out-of-order updates where the child is added before its parent, id collisions across assets.

Understand the failure class

Background: "Not found" and "does not exist" errors: why "Task not found", "No such folder", and "Can't find" fire when a lookup comes back empty — this error's family across 14 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/dd6263241186f88e. Report an issue: GitHub.

Appendix: source

Thrown at sources/editor/Stride.Assets.Presentation/AssetEditors/UIEditor/Services/UIEditorController.cs:225

        public override Task AddPart([NotNull] UIHierarchyItemViewModel parent, UIElement assetSidePart)
        {
            EnsureAssetAccess();

            var gameSidePart = ClonePartForGameSide(parent.Asset.Asset, assetSidePart);
            return InvokeAsync(() =>
            {
                Logger.Debug($"Adding element {assetSidePart.Id} to game-side scene");

                var parentId = (parent as UIElementViewModel)?.Id;
                if (parentId == null)
                {
                    RootElements[assetSidePart.Id] = gameSidePart;
                }
                else
                {
                    var parentElement = (UIElement)FindPart(parentId.Value);
                    if (parentElement == null)
                        throw new InvalidOperationException($"The given {nameof(parentId)} does not correspond to any existing part.");

                    var panel = parentElement as Panel;
                    var contentControl = parentElement as ContentControl;
                    if (panel != null)
                    {
                        GameSideNodeContainer.GetNode(panel.Children).Add(gameSidePart);
                    }
                    else if (contentControl != null)
                    {
                        if (contentControl.Content != null)
                        {
                            throw new InvalidOperationException($"The control corresponding to the given {nameof(parentId)} is a ContentControl that already has a Content.");
                        }
                        GameSideNodeContainer.GetNode(contentControl)[nameof(contentControl.Content)].Update(gameSidePart);
                    }
                }
            });
        }

View on GitHub (pinned to 96fad776d2)