{"record":{"id":"09ffb1e40381a5e7","repo":"dotnet/wpf","slug":"sr-rowcachecannotmodifynonexistentlayout","errorCode":null,"errorMessage":"SR.RowCacheCannotModifyNonExistentLayout","messagePattern":"SR\\.RowCacheCannotModifyNonExistentLayout","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/RowCache.cs","lineNumber":868,"sourceCode":"\n                //Add this page to the row\n                newRow.AddPage(pageSize);\n            }\n\n            return newRow;\n        }\n\n        /// <summary>\n        /// Given a range of pages, adds the pages to the existing row cache,\n        /// adding new rows where necessary.\n        /// </summary>\n        /// <param name=\"startPage\">The first page to add to the layout</param>\n        /// <param name=\"count\">The number of pages to add.</param>\n        private RowCacheChange AddPageRange(int startPage, int count)\n        {\n            if (!_isLayoutCompleted)\n            {\n                throw new InvalidOperationException(SR.RowCacheCannotModifyNonExistentLayout);\n            }\n\n            int currentPage = startPage;\n            int lastPage = startPage + count;\n\n            int startRow = 0;\n            int rowCount = 0;\n\n            //First we check to see if startPage is such that we'd end up skipping\n            //pages in the document -- that is, if the last page in our layout is currently\n            //10 and start is 15, we need to fill in pages 11-14 as well.\n            if (startPage > LastPageInCache + 1)\n            {\n                currentPage = LastPageInCache + 1;\n            }\n\n            //Get the last row in the layout\n            RowInfo lastRow = _rowCache[_rowCache.Count - 1];","sourceCodeStart":850,"sourceCodeEnd":886,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/RowCache.cs#L850-L886","documentation":"AddPageRange adds a range of pages to the completed row layout. If the layout was never completed (_isLayoutCompleted == false), there is no layout structure to modify, so an InvalidOperationException (SR.RowCacheCannotModifyNonExistentLayout) is thrown. It is an internal guard ensuring page-add updates only apply to a fully computed layout.","triggerScenarios":"OnPageCacheChanged (or a RowCacheChange handler) routing an Add change through AddPageRange while the row layout has not finished being computed (_isLayoutCompleted is false).","commonSituations":"Pagination updates (page count changes) arriving while the initial row layout pass is still in progress; custom paginators issuing incremental page-added notifications before the first full layout completes; race between pagination events and layout completion.","solutions":["Wait for the layout to complete before applying page-added changes (only raise page-cache changes after _isLayoutCompleted is true)","Ensure the initial RecalcRows/layout pass runs to completion before the paginator reports page changes","If implementing custom change handling, check IsLayoutCompleted before calling page-mutation APIs"],"exampleFix":"// before\ncache.AddPage(startPage, count);\n// after\nif (cache.IsLayoutCompleted)\n{\n    cache.AddPage(startPage, count);\n}\nelse\n{\n    cache.RecalcRows(0, columns);\n}","handlingStrategy":"validation","validationCode":"if (!cache.IsLayoutCompleted) { /* wait for layout or call RecalcRows */ }","typeGuard":null,"tryCatchPattern":"try { cache.AddPage(startPage, count); } catch (InvalidOperationException) { pendingChanges.Enqueue((startPage, count)); }","preventionTips":["Queue page changes until layout completion, then flush them","Never emit page-added notifications from a paginator before the first layout pass finishes"],"tags":["wpf","documents","pagination","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-21T21:30:21.729Z"}