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

  1. Defer the add until the walk completes: Dispatcher.BeginInvoke(() => AddLogicalChild(child))
  2. Move tree mutation out of property-change/layout callbacks into explicit methods or loaded events
  3. 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

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


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)