stride3d/stride · error · InvalidOperationException

The UI element 'Name=

Error message

The UI element 'Name={child.Name}' has already as visual parent the element 'Name={child.VisualParent.Name}'.

What it means

SetVisualParent assigns the visual (rendering tree) parent of a UIElement and throws ArgumentNullException for a null child, and InvalidOperationException when the child already has a different visual parent. A visual element may have exactly one visual parent so the render tree stays a tree.

Solutions

  1. Pass a non-null child element.
  2. Detach the child from its current visual parent (which removes it from the old parent's VisualChildrenCollection) before assigning a new one.
  3. Verify via child.VisualParent == null (or == newParent) before calling SetVisualParent.

Example fix

// before
UIElement.SetVisualParent(child, newParent); // child still attached elsewhere
// after
if (child.VisualParent != null && child.VisualParent != newParent)
    UIElement.SetVisualParent(child, null); // detach
UIElement.SetVisualParent(child, newParent);
Defensive patterns

Strategy: type-guard

Validate before calling

if (child != null && (child.VisualParent == null || ReferenceEquals(child.VisualParent, newParent)))
    UIElement.SetVisualParent(child, newParent);

Type guard

bool CanSetVisualParent(UIElement child, UIElement newParent) => child != null && (child.VisualParent == null || ReferenceEquals(child.VisualParent, newParent));

Try / catch

try { UIElement.SetVisualParent(child, newParent); }
catch (InvalidOperationException) { UIElement.SetVisualParent(child, null); UIElement.SetVisualParent(child, newParent); }

Prevention

When it happens

Trigger: Calling SetVisualParent(null, parent); re-parenting a child whose VisualParent is set to a different element; adding an element instance to two visual containers.

Common situations: Shared visual elements across scenes or overlays; drag-and-drop re-parenting without detaching first; z-order/overlay code that reuses one visual node.

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/3a98b96e04c8a0e2. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.UI/UIElement.cs:1134

        /// <param name="parent">The parent of the child.</param>
        protected static void SetParent([NotNull] UIElement child, [CanBeNull] UIElement parent)
        {
            if (parent != null && child.Parent != null && parent != child.Parent)
                throw new InvalidOperationException("The UI element 'Name="+child.Name+"' has already as parent the element 'Name="+child.Parent.Name+"'.");

            child.Parent = parent;
        }

        /// <summary>
        /// Set the visual parent to a child.
        /// </summary>
        /// <param name="child">The child to which set the visual parent.</param>
        /// <param name="parent">The parent of the child.</param>
        protected static void SetVisualParent([NotNull] UIElement child, [CanBeNull] UIElement parent)
        {
            if (child == null) throw new ArgumentNullException(nameof(child));
            if (parent != null && child.VisualParent != null && parent != child.VisualParent)
                throw new InvalidOperationException("The UI element 'Name=" + child.Name + "' has already as visual parent the element 'Name=" + child.VisualParent.Name + "'.");

            child.VisualParent?.VisualChildrenCollection.Remove(child);

            child.VisualParent = parent;

            if (parent != null)
            {
                child.LayoutingContext = parent.layoutingContext;
                parent.VisualChildrenCollection.Add(child);
            }
        }

        /// <summary>
        /// Calculate the intersection of the UI element and the ray.
        /// </summary>
        /// <param name="ray">The ray in world space coordinate</param>
        /// <param name="intersectionPoint">The intersection point in world space coordinate</param>
        /// <returns><value>true</value> if the two elements intersects, <value>false</value> otherwise</returns>

View on GitHub (pinned to 96fad776d2)