{"record":{"id":"62d2ed4305cba9f3","repo":"dotnet/wpf","slug":"sr-cannotmodifylogicalchildrenduringtreewalk-62d2ed","errorCode":null,"errorMessage":"SR.CannotModifyLogicalChildrenDuringTreeWalk","messagePattern":"SR\\.CannotModifyLogicalChildrenDuringTreeWalk","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/FrameworkElementTemplate.cs","lineNumber":256,"sourceCode":"                                    {\n                                        return _parent;\n                                    }\n\n                                    // mark whether Add should be called *before* or *after* the element adds it to its structure\n                                    /// <summary>\n                                    ///     Called by an element when that element adds the given object to\n                                    ///     its logical tree.  FrameworkElement updates the affected\n                                    ///     logical tree parent pointers to keep in sync with this insertion\n                                    /// </summary>\n                                    protected internal void AddLogicalChild(object child)\n                                    {\n                                        if (child != null)\n                                        {\n                                            // It is invalid to modify the children collection that we\n                                            // might be iterating during a property invalidation tree walk.\n                                            if (IsLogicalChildrenIterationInProgress)\n                                            {\n                                                throw new InvalidOperationException(SR.CannotModifyLogicalChildrenDuringTreeWalk);\n                                            }\n\n                                            // Now that the child is going to be added, the FE/FCE construction is considered finished,\n                                            // so we do not expect a change of InheritanceBehavior property,\n                                            // so we can pick up properties from styles and resources.\n                                            TryFireInitialized();\n\n                                            bool exceptionThrown = true;\n                                            try\n                                            {\n                                                HasLogicalChildren = true;\n\n                                                // Child is present; reparent him to this element\n                                                FrameworkObject fo = new FrameworkObject(child as DependencyObject);\n                                                fo.ChangeLogicalParent(this);\n\n                                                exceptionThrown = false;\n                                            }","sourceCodeStart":238,"sourceCodeEnd":274,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/WpfGfx/codegen/mcg/generators/FrameworkElementTemplate.cs#L238-L274","documentation":"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.","triggerScenarios":"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.","commonSituations":"PropertyChangedCallback that adds children reactively; ItemsChanged/CollectionChanged handlers that mutate the logical tree; subclass OnApplyTemplate/measure overrides inserting elements.","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"],"exampleFix":"// before\nvoid OnPropertyChanged(...) { AddLogicalChild(newChild); }\n// after\nvoid OnPropertyChanged(...) { Dispatcher.BeginInvoke(() => AddLogicalChild(newChild)); }","handlingStrategy":"try-catch","validationCode":"if (this.IsLogicalChildrenIterationInProgress) { pendingChildren.Enqueue(child); return; } // defer instead of adding now","typeGuard":null,"tryCatchPattern":"try { AddLogicalChild(child); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"tree walk\")) { Dispatcher.BeginInvoke(() => AddLogicalChild(child)); }","preventionTips":["Never mutate the logical tree inside PropertyChangedCallbacks","Defer tree changes with Dispatcher.BeginInvoke during invalidation","Move reactive child-creation to Loaded/Initialized handlers"],"tags":["wpf","logical-tree","property-system","invalid-operation"],"backgroundTag":"invalid-state-transition","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}