dotnet/wpf · error · InvalidOperationException
SR.CannotBeSelfParent
Error message
SR.CannotBeSelfParent
What it means
ChangeLogicalParent also rejects self-parenting: if newParent == this, InvalidOperationException (CannotBeSelfParent) is thrown. Allowing an element to be its own logical parent would create a cycle, breaking tree invariants and infinite-walking the tree.
Solutions
- Verify the newParent argument is the intended ancestor, not the element itself.
- Break data cycles before they reach the visual/logical tree (e.g. detect recursion in your model).
- Add an assertion/guard in custom container code that child != this before attaching.
Example fix
// before
if (parent == null) parent = this; // wrong fallback
this.ChangeLogicalParent(parent);
// after
if (parent == null || parent == this)
throw new ArgumentException("Invalid logical parent");
this.ChangeLogicalParent(parent); Defensive patterns
Strategy: validation
Validate before calling
if (ReferenceEquals(newParent, element)) throw new ArgumentException("Element cannot be its own logical parent"); Type guard
static bool IsValidParent(DependencyObject self, DependencyObject candidate) => candidate != null && !ReferenceEquals(candidate, self);
Try / catch
try { element.ChangeLogicalParent(newParent); } catch (InvalidOperationException ex) when (ex.Message.Contains("self")) { Log("cycle detected"); } Prevention
- Assert child != this in any custom Add/Change parent code.
- Detect recursive object graphs in your model before rendering them.
- Keep parent assignment centralized so accidental self-assignment is impossible.
When it happens
Trigger: Calling ChangeLogicalParent with the element itself, or code paths (AddLogicalChild on self, self-referential binding/content assignment) that end up attaching an element as its own child/parent.
Common situations: Recursive data structures rendered directly into themselves; programming errors in custom containers where 'this' is passed instead of the intended child; cyclic content assignment in templates.
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/d72ca5d113ea58a5.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Generated/FrameworkContentElement.cs:306
// (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;
DependencyObject oldParent = _parent;
OnNewParent(newParent);
// Update Has[Loaded/Unloaded]Handler Flags
BroadcastEventHelper.AddOrRemoveHasLoadedChangeHandlerFlag(this, oldParent, newParent);View on GitHub (pinned to 81131a70a4)