{"record":{"id":"910357488c565714","repo":"dotnet/wpf","slug":"sr-flowdocumentinvalidcontnetchange-flowdocument","errorCode":null,"errorMessage":"SR.FlowDocumentInvalidContnetChange","messagePattern":"SR\\.FlowDocumentInvalidContnetChange","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FlowDocument.cs","lineNumber":796,"sourceCode":"\n            if (e.IsAValueChange || e.IsASubPropertyChange)\n            {\n                // Skip caches invalidation if content has not been formatted yet - non of caches are valid,\n                // so they will be aquired during first formatting (full format).\n                if (_structuralCache != null && _structuralCache.IsFormattedOnce)\n                {\n                    FrameworkPropertyMetadata fmetadata = e.Metadata as FrameworkPropertyMetadata;\n                    if (fmetadata != null)\n                    {\n                        bool affectsRender = (fmetadata.AffectsRender &&\n                            (e.IsAValueChange || !fmetadata.SubPropertiesDoNotAffectRender));\n                        if (fmetadata.AffectsMeasure || fmetadata.AffectsArrange || affectsRender || fmetadata.AffectsParentMeasure || fmetadata.AffectsParentArrange)\n                        {\n                            // Detect invalid content change operations.\n                            if (_structuralCache.IsFormattingInProgress)\n                            {\n                                _structuralCache.OnInvalidOperationDetected();\n                                throw new InvalidOperationException(SR.FlowDocumentInvalidContnetChange);\n                            }\n\n                            // None of FlowDocument properties can invalidate structural caches (the NameTable),\n                            // but most likely it invalidates format caches. Invalidate all format caches\n                            // accumulated in the NameTable.\n                            _structuralCache.InvalidateFormatCache(!affectsRender);\n\n                            // Notify formatter about content invalidation.\n                            _formatter?.OnContentInvalidated(!affectsRender);\n                        }\n                    }\n                }\n            }\n        }\n\n        /// <summary>\n        /// Creates AutomationPeer (<see cref=\"ContentElement.OnCreateAutomationPeer\"/>)\n        /// </summary>","sourceCodeStart":778,"sourceCodeEnd":814,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/FlowDocument.cs#L778-L814","documentation":"FlowDocument.OnPropertyChanged detects a property change (affecting measure/arrange/render) arriving while formatting is in progress, i.e. during layout. Re-entrantly modifying the document during its own formatting pass would corrupt the StructuralCache/NameTable, so the library flags the operation via OnInvalidOperationDetected and throws InvalidOperationException(SR.FlowDocumentInvalidContnetChange).","triggerScenarios":"Changing a FlowDocument or descendant DependencyProperty (e.g. setting PagePadding, ColumnWidth, fonts) from inside a measure/arrange pass, layout event, or a property-changed callback triggered while _structuralCache.IsFormattingInProgress is true.","commonSituations":"Setting FlowDocument properties inside a Loaded event, size-changed handler, or a binding that updates during layout; modifying page/column properties from custom pagination code that runs during formatting.","solutions":["Defer property changes until after layout: use Dispatcher.BeginInvoke(DispatcherPriority.Background, ...) to apply the change","Set properties before the document is displayed or outside measure/arrange callbacks","Avoid binding FlowDocument layout-affecting properties to sources that update during rendering; use OneTime bindings or pre-set values","Catch InvalidOperationException to log the re-entrancy and retry the change after layout completes"],"exampleFix":"// before\n// inside OnRender/measure handler:\ndocument.PagePadding = new Thickness(10); // throws if formatting in progress\n// after\nDispatcher.BeginInvoke(DispatcherPriority.Background,\n    new Action(() => document.PagePadding = new Thickness(10)));","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { doc.PagePadding = value; }\ncatch (InvalidOperationException) {\n    Dispatcher.BeginInvoke(DispatcherPriority.Background,\n        new Action(() => doc.PagePadding = value));\n}","preventionTips":["Never change FlowDocument properties inside measure/arrange or Loaded callbacks","Defer layout-affecting changes via Dispatcher.BeginInvoke at background priority","Avoid TwoWay bindings on layout-affecting properties that update during render","Set page/column configuration before the document is shown"],"tags":["wpf","flowdocument","layout","reentrancy"],"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-21T21:30:21.729Z"}