dotnet/wpf · error · InvalidOperationException

SR.CannotModifyVisualChildrenDuringTreeWalk

Error message

SR.CannotModifyVisualChildrenDuringTreeWalk

What it means

Thrown by VisualCollection.ConnectChild when children are added while the owner visual is iterating its children collection during a property-invalidation tree walk (IsVisualChildrenIterationInProgress). Mutating the collection during that walk would corrupt the in-progress iteration, so WPF fails fast with InvalidOperationException.

Solutions

  1. Defer the mutation: Dispatcher.BeginInvoke(DispatcherPriority.Background, () => collection.Add(child)) so it runs after the walk completes.
  2. Buffer pending additions in a list during the callback and apply them after (e.g. at Loaded or next layout pass).
  3. Restructure so children are added before triggering the property change that starts the walk.

Example fix

// before
protected override void OnRenderSizeChanged(SizeChangedInfo info)
{
    Children.Add(BuildChild()); // may throw during a tree walk
}
// after
Dispatcher.BeginInvoke(DispatcherPriority.Background,
    new Action(() => Children.Add(BuildChild())));
Defensive patterns

Strategy: try-catch

Validate before calling

if (((Visual)VisualTreeHelper.GetParent(child) ?? owner).CheckAccess()
    && owner.IsVisualChildrenIterationInProgress /* requires internal access */) { /* defer */ }

Try / catch

try { collection.Insert(0, child); }
catch (InvalidOperationException) {
    Dispatcher.BeginInvoke(DispatcherPriority.Background,
        new Action(() => collection.Insert(0, child)));
}

Prevention

When it happens

Trigger: Calling Add or Insert (which call ConnectChild) from within a callback that runs during visual-tree property invalidation — e.g. inside OnVisualChildrenChanged during an active walk, or property-changed handlers that synchronously add children while WPF is enumerating the same collection.

Common situations: Custom panels adding children in response to property invalidations; code hooks (e.g. AutomationPeer, layout notifications) that mutate children re-entrantly during tree walks.

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/096bbda23c481ea6. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/VisualCollection.cs:375

        private void ConnectChild(int index, Visual value)
        {
            //
            // -- 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.
            //
            _owner.VerifyAccess();
            value.VerifyAccess();
            
            // It is invalid to modify the children collection that we 
            // might be iterating during a property invalidation tree walk.
            if (_owner.IsVisualChildrenIterationInProgress)
            {
                throw new InvalidOperationException(SR.CannotModifyVisualChildrenDuringTreeWalk);
            }

            Debug.Assert(value != null);
            Debug.Assert(_items[index] == null);
            Debug.Assert(value._parent == null);
            Debug.Assert(!value.IsRootElement);

            value._parentIndex = index;
            _items[index] = value;
            IncrementVersion();

            // Notify the Visual tree about the children changes. 
            _owner.InternalAddVisualChild(value);
        }

        /// <summary>
        /// Disconnects a child.
        /// </summary>

View on GitHub (pinned to 81131a70a4)