dotnet/wpf · error · InvalidOperationException
SR.HasLogicalParent
Error message
SR.HasLogicalParent
What it means
ChangeLogicalParent (internal logical-tree plumbing used by FrameworkElement.AddLogicalChild/parent assignment) enforces that a child must be detached from its current logical parent before being attached to a new one. If _parent is non-null and differs from newParent, WPF throws InvalidOperationException (HasLogicalParent) to prevent 'child stealing' and corrupt trees.
Solutions
- Remove the child from its current parent first (oldParent.RemoveLogicalChild(child) or remove from the panel's Children) before adding it to the new parent.
- Use XamlReader/clone or construct a new element instance if the element must appear in two places.
- For ContentControls, reassign the old holder's Content to null before setting it on the new holder.
Example fix
// before panelB.Children.Add(sharedButton); // InvalidOperationException: has logical parent panelA // after panelA.Children.Remove(sharedButton); panelB.Children.Add(sharedButton);
Defensive patterns
Strategy: validation
Validate before calling
var logicalParent = LogicalTreeHelper.GetParent(child);
if (logicalParent != null && logicalParent != newParent)
throw new InvalidOperationException("Child already has a logical parent; detach first."); Type guard
bool IsOrphan(FrameworkElement child) => LogicalTreeHelper.GetParent(child) == null;
Try / catch
try
{
newParent.AddLogicalChild(child);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("parent"))
{
Log.Warn("Child already attached to another logical parent.", ex);
} Prevention
- Always remove an element from its current parent before adding it elsewhere.
- Never share one element instance between two containers; clone or create new instances instead.
- Null out Content/Child on the old holder before reassigning to a new holder.
When it happens
Trigger: Adding an element that already has a logical parent to a second parent: calling newParent.AddLogicalChild(child) where child.Parent (or logical parent) is another element; reparenting without removing from the old parent first; sharing one child instance between two containers.
Common situations: Reusing a single UI element instance in multiple Panels/Tabs; moving controls between containers without detaching; content assigned to two ContentControls simultaneously.
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
- SR.CannotBeSelfParent
- SR.CannotBeSelfParent
- SR.CannotModifyLogicalChildrenDuringTreeWalk
- SR.CannotModifyLogicalChildrenDuringTreeWalk
- SR.HasLogicalParent
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/3947078da9ec318b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Generated/FrameworkElement.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)