dotnet/wpf · error · InvalidOperationException

SR.HasLogicalParent

Error message

SR.HasLogicalParent

What it means

ChangeLogicalParent enforces that a logical child has exactly one parent: the existing _parent must be dropped (set to null) or be the same as newParent before re-attaching. Otherwise InvalidOperationException (HasLogicalParent) is thrown, preventing 'child stealing' and illegal tree states (see WPF bug 970706).

Solutions

  1. Remove the child from its current logical parent before adding it to the new one.
  2. Use separate element instances per location instead of sharing one instance.
  3. If reparenting intentionally, set (oldParent).RemoveLogicalChild(child) first, then attach.

Example fix

// before
panelB.Children.Add(sharedElement); // still parented to panelA
// after
panelA.Children.Remove(sharedElement);
panelB.Children.Add(sharedElement);
Defensive patterns

Strategy: validation

Validate before calling

if (LogicalTreeHelper.GetParent(child) != null && LogicalTreeHelper.GetParent(child) != newParent)
    ((FrameworkElement)LogicalTreeHelper.GetParent(child)).RemoveLogicalChild(child); // detach first

Type guard

static bool IsOrphan(DependencyObject child) => new FrameworkObject(child).Parent == null;

Try / catch

try { newParent.AddLogicalChild(child); } catch (InvalidOperationException ex) when (ex.Message.Contains("parent")) { /* detach from old parent then retry */ }

Prevention

When it happens

Trigger: Assigning an element that already has a logical parent to a second parent — e.g. adding the same UIElement to two panels, reusing an element instance in two ContentControls, or reparenting without detaching first.

Common situations: Reusing control instances across pages/panels; moving an element between containers without removing it first; data-binding mistakes that reuse the same visual as multiple items' content.

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 dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/73fb7d5704f55fc9. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Generated/FrameworkContentElement.cs:300

            ///////////////////

            //
            // -- Approved By The Core Team --
            //
            // Do not allow foreign threads to change the tree.
            // (This is a noop if this object is not assigned to a Dispatcher.)
            //
            // We also need to ensure that the tree is homogenous with respect
            // to the dispatchers that the elements belong to.
            //
            this.VerifyAccess();
            newParent?.VerifyAccess();

            // Logical Parent must first be dropped before you are attached to a newParent
            // This mitigates illegal tree state caused by logical child stealing as illustrated in bug 970706
            if (_parent != null && newParent != null && _parent != newParent)
            {
                throw new System.InvalidOperationException(SR.HasLogicalParent);
            }

            // Trivial check to avoid loops
            if (newParent == this)
            {
                throw new System.InvalidOperationException(SR.CannotBeSelfParent);
            }

            // invalid during a VisualTreeChanged event
            VisualDiagnostics.VerifyVisualTreeChange(this);

            // Logical Parent implies no InheritanceContext
            if (newParent != null)
            {
                ClearInheritanceContext();
            }

            IsParentAnFE = newParent is FrameworkElement;

View on GitHub (pinned to 81131a70a4)