dotnet/wpf · error · InvalidOperationException
SR.CannotModifyLogicalChildrenDuringTreeWalk
Error message
SR.CannotModifyLogicalChildrenDuringTreeWalk
What it means
Adding a logical child while a property-invalidation tree walk is iterating the children collection is forbidden: FrameworkElement guards with IsLogicalChildrenIterationInProgress and throws InvalidOperationException(SR.CannotModifyLogicalChildrenDuringTreeWalk). This protects against corrupting the logical tree during invalidation recursion.
Solutions
- Defer the add until the walk completes: Dispatcher.BeginInvoke(() => AddLogicalChild(child))
- Move tree mutation out of property-change/layout callbacks into explicit methods or loaded events
- Use a flag/queue pattern: record pending children, add them after invalidation finishes
Example fix
// before
void OnPropertyChanged(...) { AddLogicalChild(newChild); }
// after
void OnPropertyChanged(...) { Dispatcher.BeginInvoke(() => AddLogicalChild(newChild)); } Defensive patterns
Strategy: try-catch
Validate before calling
if (this.IsLogicalChildrenIterationInProgress) { pendingChildren.Enqueue(child); return; } // defer instead of adding now Try / catch
try { AddLogicalChild(child); } catch (InvalidOperationException ex) when (ex.Message.Contains("tree walk")) { Dispatcher.BeginInvoke(() => AddLogicalChild(child)); } Prevention
- Never mutate the logical tree inside PropertyChangedCallbacks
- Defer tree changes with Dispatcher.BeginInvoke during invalidation
- Move reactive child-creation to Loaded/Initialized handlers
When it happens
Trigger: Calling AddLogicalChild(child) (or a generated content-collection add that routes through it) from inside a property-changed callback, layout/measure pass, or any event raised synchronously during a tree walk.
Common situations: PropertyChangedCallback that adds children reactively; ItemsChanged/CollectionChanged handlers that mutate the logical tree; subclass OnApplyTemplate/measure overrides inserting elements.
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.HasLogicalParent
- SR.HasLogicalParent
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/62d2ed4305cba9f3.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/FrameworkElementTemplate.cs:256
{
return _parent;
}
// mark whether Add should be called *before* or *after* the element adds it to its structure
/// <summary>
/// Called by an element when that element adds the given object to
/// its logical tree. FrameworkElement updates the affected
/// logical tree parent pointers to keep in sync with this insertion
/// </summary>
protected internal void AddLogicalChild(object child)
{
if (child != null)
{
// It is invalid to modify the children collection that we
// might be iterating during a property invalidation tree walk.
if (IsLogicalChildrenIterationInProgress)
{
throw new InvalidOperationException(SR.CannotModifyLogicalChildrenDuringTreeWalk);
}
// Now that the child is going to be added, the FE/FCE construction is considered finished,
// so we do not expect a change of InheritanceBehavior property,
// so we can pick up properties from styles and resources.
TryFireInitialized();
bool exceptionThrown = true;
try
{
HasLogicalChildren = true;
// Child is present; reparent him to this element
FrameworkObject fo = new FrameworkObject(child as DependencyObject);
fo.ChangeLogicalParent(this);
exceptionThrown = false;
}View on GitHub (pinned to 81131a70a4)