{"record":{"id":"d1e58408fecd6335","repo":"dotnet/wpf","slug":"sr-textcontainerchangingreentrancyinvalid-d1e584","errorCode":null,"errorMessage":"SR.TextContainerChangingReentrancyInvalid","messagePattern":"SR\\.TextContainerChangingReentrancyInvalid","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/FlowDocumentPaginator.cs","lineNumber":83,"sourceCode":"        /// <exception cref=\"ArgumentOutOfRangeException\">\n        /// Throws ArgumentOutOfRangeException if PageNumber is negative.\n        /// </exception>\n        public override void GetPageAsync(int pageNumber, object userState)\n        {\n            // Page number cannot be negative.\n            if (pageNumber < 0)\n            {\n                throw new ArgumentOutOfRangeException(nameof(pageNumber), SR.IDPNegativePageNumber);\n            }\n\n            // Reentrancy check.\n            if (_document.StructuralCache.IsFormattingInProgress)\n            {\n                throw new InvalidOperationException(SR.FlowDocumentFormattingReentrancy);\n            }\n            if (_document.StructuralCache.IsContentChangeInProgress)\n            {\n                throw new InvalidOperationException(SR.TextContainerChangingReentrancyInvalid);\n            }\n\n            DocumentPage page = null;\n\n            if (!_backgroundPagination)\n            {\n                page = GetPage(pageNumber);\n            }\n            else\n            {\n                // If entire content has been already pre-paginated (BreakRecordTable is clean)\n                // and requesting non-existing page number, return DocumentPage.Missing.\n                if (_brt.IsClean && !_brt.HasPageBreakRecord(pageNumber))\n                {\n                    page = DocumentPage.Missing;\n                }\n\n                if (_brt.HasPageBreakRecord(pageNumber))","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/FlowDocumentPaginator.cs#L65-L101","documentation":"FlowDocumentPaginator.GetPageAsync throws InvalidOperationException(SR.TextContainerChangingReentrancyInvalid) when called while a content change is in progress on the document's TextContainer (StructuralCache.IsContentChangeInProgress). Formatting cannot start against a mutating TextContainer; WPF throws rather than produce inconsistent pages.","triggerScenarios":"Calling GetPageAsync while the FlowDocument is inside a TextContainer change scope — e.g. from a TextChanged/ContentChanged event handler, from code executed during paragraph/text insertion, or from a nested API call that mutates the document while pagination is requested on the same call stack.","commonSituations":"Handlers that update document text and immediately request pages; RichTextBox automation that edits content and paginates in the same event; printing triggered from within a text-editing transaction.","solutions":["Defer GetPageAsync until the content change completes — post it with Dispatcher.BeginInvoke from change handlers.","Never request pagination from within ContentChanged/TextChanged handlers on the same document.","Complete all document edits before initiating printing/pagination.","If you must react to edits, mark a dirty flag and paginate on a subsequent dispatcher pass."],"exampleFix":"// before\nrichTextBox.TextChanged += (s, e) => {\n    paginator.GetPageAsync(0, null); // content change in progress\n};\n// after\nrichTextBox.TextChanged += (s, e) => {\n    Dispatcher.BeginInvoke(new Action(() => paginator.GetPageAsync(0, null)),\n        System.Windows.Threading.DispatcherPriority.Background);\n};","handlingStrategy":"validation","validationCode":"if (!document.StructuralCache.IsContentChangeInProgress &&\n    !document.StructuralCache.IsFormattingInProgress)\n    paginator.GetPageAsync(pageNumber, userState);","typeGuard":"bool CanPaginate(FlowDocument doc) => !doc.StructuralCache.IsContentChangeInProgress && !doc.StructuralCache.IsFormattingInProgress;","tryCatchPattern":"try { paginator.GetPageAsync(n, state); }\ncatch (InvalidOperationException) {\n    Dispatcher.BeginInvoke(new Action(() => paginator.GetPageAsync(n, state)), DispatcherPriority.Background);\n}","preventionTips":["Do not paginate from TextChanged/ContentChanged handlers","Finish document edits before initiating printing/pagination","Mark dirty and paginate on the next idle dispatcher pass","Keep edit transactions short and non-nested"],"tags":["wpf","reentrancy","textcontainer","pagination"],"backgroundTag":"unsupported-operation","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"}