stride3d/stride · error · InvalidOperationException

(Name= ) already has a content.

Error message

{nameof(ContentControl)} (Name={control.Name}) already has a content.

What it means

In UIAssetPropertyGraph, when a new UI child is attached to a ContentControl parent, the Quantum node backing ContentControl.Content must be null. If the control already has content, AddChildPartToParentPart throws InvalidOperationException, because a ContentControl can hold exactly one child.

Solutions

  1. Remove the existing child of the ContentControl before adding the new one
  2. Use a Panel (StackPanel/Grid) instead of ContentControl when multiple children are needed
  3. If caused by a stale node, reopen/reload the UI asset to resynchronize the Quantum container
  4. Delete and recreate the corrupted ContentControl in the editor

Example fix

// before
contentControl.Content = imageA;
graph.AddChildPartToParentPart(contentControl, imageB); // throws
// after
contentControl.Content = null;
graph.AddChildPartToParentPart(contentControl, imageB);
Defensive patterns

Strategy: type-guard

Validate before calling

var node = Container.NodeContainer.GetOrCreateNode(control)[nameof(ContentControl.Content)];
if (node.Retrieve() != null) { /* remove existing child or choose a Panel parent first */ }

Type guard

bool canAddChild(UIElement parent) =>
    parent is Panel || (parent is ContentControl c &&
        Container.NodeContainer.GetOrCreateNode(c)[nameof(ContentControl.Content)].Retrieve() == null);

Try / catch

try
{
    graph.AddChildPartToParentPart(parent, child);
}
catch (InvalidOperationException)
{
    // ContentControl already occupied: clear content or use a Panel
}

Prevention

When it happens

Trigger: Adding a second child to a ContentControl in the UI editor / asset graph, or programmatically calling AddChildPartToParentPart on a ContentControl whose Content node already stores a part.

Common situations: Dragging a new element onto a Button/ContentControl that already contains one, restoring a UI asset where a stale Quantum node still references a removed control, or duplicated undo/redo operations re-adding the same child.

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


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

Appendix: source

Thrown at sources/engine/Stride.Assets/Quantum/UIAssetPropertyGraph.cs:63

                if (memberContent.Name == nameof(ContentControl.Content) && typeof(ContentControl).IsAssignableFrom(memberContent.Parent.Type))
                    return true;
            }
            if ((node as IObjectNode)?.Type == typeof(UIElementCollection))
            {
                return true;
            }
            return false;
        }

        /// <inheritdoc/>
        protected override void AddChildPartToParentPart(UIElement parentPart, UIElement childPart, int index)
        {
            var control = parentPart as ContentControl;
            if (control != null)
            {
                var node = Container.NodeContainer.GetOrCreateNode(control)[nameof(ContentControl.Content)];
                if (node.Retrieve() != null)
                    throw new InvalidOperationException($"{nameof(ContentControl)} (Name={control.Name}) already has a content.");

                node.Update(childPart);
                return;
            }
            var panel = parentPart as Panel;
            if (panel != null)
            {
                var node = Container.NodeContainer.GetOrCreateNode(panel)[nameof(Panel.Children)].Target;
                if (index < 0)
                    node.Add(childPart);
                else
                    node.Add(childPart, new NodeIndex(index));
                return;
            }
            throw new NotSupportedException();
        }

        /// <inheritdoc/>

View on GitHub (pinned to 96fad776d2)