{"record":{"id":"86ec124903c8af4c","repo":"dotnet/wpf","slug":"sr-textcontainerchangingreentrancyinvalid-textflow","errorCode":null,"errorMessage":"SR.TextContainerChangingReentrancyInvalid","messagePattern":"SR\\.TextContainerChangingReentrancyInvalid","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextFlow.cs","lineNumber":1520,"sourceCode":"\n        // ------------------------------------------------------------------\n        // Ensures none of our methods can be called during measure/arrange/content change.\n        // ------------------------------------------------------------------\n        private void VerifyReentrancy()\n        {\n            if(CheckFlags(Flags.MeasureInProgress))\n            {\n                throw new InvalidOperationException(SR.MeasureReentrancyInvalid);\n            }\n\n            if(CheckFlags(Flags.ArrangeInProgress))\n            {\n                throw new InvalidOperationException(SR.ArrangeReentrancyInvalid);\n            }\n\n            if(CheckFlags(Flags.ContentChangeInProgress))\n            {\n                throw new InvalidOperationException(SR.TextContainerChangingReentrancyInvalid);\n            }\n        }\n\n        // ------------------------------------------------------------------\n        /// CalculateViewportRect - Called to calculate the visible rect for this element\n        // ------------------------------------------------------------------\n        private Rect CalculateViewportRect()\n        {\n            Rect visibleRect = new Rect(0, 0, RenderSize.Width, RenderSize.Height);\n\n            Visual visual = VisualTreeHelper.GetParent(this) as Visual;\n\n            while(visual != null && visibleRect != Rect.Empty)\n            {                \n                if(VisualTreeHelper.GetClip(visual) != null)\n                {\n                    GeneralTransform transform = this.TransformToAncestor(visual).Inverse;\n                    ","sourceCodeStart":1502,"sourceCodeEnd":1538,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Documents/TextFlow.cs#L1502-L1538","documentation":"VerifyReentrancy also rejects calls while a TextContainer change is in progress: if Flags.ContentChangeInProgress is set, it throws InvalidOperationException(SR.TextContainerChangingReentrancyInvalid). This prevents mutating or querying the text layout while the TextTree is inside a change block (e.g. from a TextContainer.Changing handler).","triggerScenarios":"Calling a public TextFlow method from a TextContainer.Changing event handler, from within a BeginChange/EndChange scope on the TextContainer, or from any callback invoked synchronously during content change.","commonSituations":"Developers hooking TextContainer.Changing to update UI or reformat text; code that reacts to document edits immediately instead of deferring to the ContentChanged event.","solutions":["Handle TextContainer.ContentChanged (after the change completes) instead of Changing.","If you must react during Changing, post work with Dispatcher.BeginInvoke so it runs after the change block closes.","Ensure you do not call TextFlow APIs from within your own BeginChange/EndChange scopes that are nested inside layout."],"exampleFix":"// before\ntextContainer.Changing += (s, e) => Reformat(_textFlow);\n// after\ntextContainer.ContentChanged += (s, e) => Dispatcher.BeginInvoke(() => Reformat(_textFlow));","handlingStrategy":"validation","validationCode":"// Prefer: only react after the change completes.\nif (!isInsideContentChangeScope) DoTextFlowWork(); // track your own BeginChange scopes","typeGuard":null,"tryCatchPattern":"try { DoTextFlowWork(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"changing\")) { Dispatcher.BeginInvoke(DoTextFlowWork); }","preventionTips":["Use TextContainer.ContentChanged instead of Changing to react to edits","Never call TextFlow APIs from within a BeginChange/EndChange block","Queue post-change work on the dispatcher"],"tags":["wpf","reentrancy","textcontainer"],"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"}