{"record":{"id":"8e13db3db5c0f5bf","repo":"dotnet/wpf","slug":"sr-format-sr-cannotremoveunrealizeditems-index-count","errorCode":null,"errorMessage":"SR.Format(SR.CannotRemoveUnrealizedItems, index, count)","messagePattern":"SR\\.Format\\(SR\\.CannotRemoveUnrealizedItems, index, count\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs","lineNumber":302,"sourceCode":"            ItemBlock block;\n\n            // find the leftmost item to remove\n            int offsetL = index;\n            for (block = _itemMap.Next;  block != _itemMap;  block = block.Next)\n            {\n                if (offsetL < block.ContainerCount)\n                    break;\n\n                offsetL -= block.ContainerCount;\n            }\n            RealizedItemBlock blockL = block as RealizedItemBlock;\n\n            // find the rightmost item to remove\n            int offsetR = offsetL + count - 1;\n            for (; block != _itemMap;  block = block.Next)\n            {\n                if (!(block is RealizedItemBlock))\n                    throw new InvalidOperationException(SR.Format(SR.CannotRemoveUnrealizedItems, index, count));\n\n                if (offsetR < block.ContainerCount)\n                    break;\n\n                offsetR -= block.ContainerCount;\n            }\n            RealizedItemBlock blockR = block as RealizedItemBlock;\n\n            // de-initialize the containers that are being removed\n            RealizedItemBlock rblock = blockL;\n            int offset = offsetL;\n            while (rblock != blockR || offset <= offsetR)\n            {\n                DependencyObject container = rblock.ContainerAt(offset);\n\n                UnlinkContainerFromItem(container, rblock.ItemAt(offset));\n                // DataGrid generates non-GroupItem for NewItemPlaceHolder\n                // Dont recycle in this case.","sourceCodeStart":284,"sourceCodeEnd":320,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs#L284-L320","documentation":"Remove/Recycle walks the item map blocks from the given position and requires every block in the removal range to be a RealizedItemBlock. If it encounters an unrealized block within the range, the generator throws InvalidOperationException (CannotRemoveUnrealizedItems) because unrealized items have no containers to remove or recycle.","triggerScenarios":"Calling Remove(position, count, ...) where the range spans unrealized (not yet generated) items — e.g. removing a batch larger than the realized region, or using a stale index after items were virtualized away.","commonSituations":"Custom VirtualizingPanels recycling a viewport range after a collection change shifted indices; removing a whole page of items when only part was ever generated.","solutions":["Ensure the removal range contains only realized items: check ContainerFromIndex/ShouldRealize before including an item.","Recalculate the position and count against the current item map after any CollectionChanged event.","Use Recycle semantics only on containers you actually obtained from GenerateNext in this pass."],"exampleFix":"// before\ngenerator.Remove(startPos, pageItemCount, true); // range may include unrealized items\n\n// after\nint realized = 0;\nwhile (realized < pageItemCount && generator.ContainerFromIndex(firstIndex + realized) != null)\n    realized++;\nif (realized > 0)\n    generator.Remove(startPos, realized, true);","handlingStrategy":"validation","validationCode":"int realizedCount = 0;\nfor (int i = firstIndex; i <= lastIndex; i++)\n    if (generator.ContainerFromIndex(i) != null) realizedCount++;\nif (realizedCount != lastIndex - firstIndex + 1)\n    throw new InvalidOperationException(\"Range includes unrealized items; cannot Remove\");","typeGuard":"static bool AllRealized(ItemContainerGenerator g, int from, int count) =>\n    Enumerable.Range(from, count).All(i => g.ContainerFromIndex(i) != null);","tryCatchPattern":"try { generator.Remove(pos, count, true); }\ncatch (InvalidOperationException) { /* some items unrealized: re-derive range */ }","preventionTips":["Refresh positions after every CollectionChanged before recycling.","Only recycle containers obtained from GenerateNext in the current pass.","Clamp removal ranges to the realized window."],"tags":["wpf","itemcontainergenerator","virtualization","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"}