{"record":{"id":"5b539df0eb71f132","repo":"dotnet/wpf","slug":"sr-format-sr-removerequiresoffsetzero-position-index","errorCode":null,"errorMessage":"SR.Format(SR.RemoveRequiresOffsetZero, position.Index, position.Offset)","messagePattern":"SR\\.Format\\(SR\\.RemoveRequiresOffsetZero, position\\.Index, position\\.Offset\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs","lineNumber":272,"sourceCode":"            object item = container.ReadLocalValue(ItemForItemContainerProperty);\n            Host.PrepareItemContainer(container, item);\n        }\n\n        /// <summary>\n        /// Remove generated elements.\n        /// </summary>\n        void IItemContainerGenerator.Remove(GeneratorPosition position, int count)\n        {\n            Remove(position, count, /*isRecycling = */ false);\n        }\n\n        /// <summary>\n        /// Remove generated elements.\n        /// </summary>\n        private void Remove(GeneratorPosition position, int count, bool isRecycling)\n        {\n            if (position.Offset != 0)\n                throw new ArgumentException(SR.Format(SR.RemoveRequiresOffsetZero, position.Index, position.Offset), nameof(position));\n            if (count <= 0)\n                throw new ArgumentException(SR.Format(SR.RemoveRequiresPositiveCount, count), nameof(count));\n\n            if (_itemMap == null)\n            {\n                // ignore reentrant call (during RemoveAllInternal)\n                Debug.Fail(\"Unexpected reentrant call to ICG.Remove\");\n                return;\n            }\n\n            int index = position.Index;\n            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)","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs#L254-L290","documentation":"ItemContainerGenerator.Remove (and Recycle) requires the GeneratorPosition to have Offset == 0, meaning it points exactly at a realized item. A non-zero offset would refer to a point between items or an unrealized slot, which Remove cannot resolve, so it throws ArgumentException naming the offending index and offset.","triggerScenarios":"Calling IItemContainerGenerator.Remove(position, count, isRecycling) with a position whose Offset is non-zero (e.g. a position obtained for a spot inside a group or from IndexOf on an unrealized item).","commonSituations":"Custom panels computing positions by hand and forgetting that Remove needs positions normalized to realized containers; mixing positions meant for RemoveAllInternal with manual Remove calls.","solutions":["Normalize the GeneratorPosition so Offset is 0 before calling Remove (use GeneratorPositionFromIndex on a realized index).","Verify the item is realized (ContainerFromIndex returns non-null) before removing; use Recycle-like semantics otherwise.","If removing everything, call RemoveAllInternal/RemoveAll instead of looping manual Remove calls."],"exampleFix":"// before\nvar pos = generator.GeneratorPositionFromIndex(i);\nif (pos.Offset != 0) generator.Remove(pos, 1, true); // throws\n\n// after\nvar pos = generator.GeneratorPositionFromIndex(i);\nif (pos.Offset == 0)\n    generator.Remove(pos, 1, true);\nelse\n    generator.Remove(new GeneratorPosition(pos.Index + 1, 0), 1, true); // adjust to realized boundary","handlingStrategy":"validation","validationCode":"var pos = generator.GeneratorPositionFromIndex(i);\nif (pos.Offset != 0)\n    throw new ArgumentException(\"Remove requires a realized position (Offset == 0)\");\nif (count > 0)\n    generator.Remove(pos, count, isRecycling);","typeGuard":"static bool IsRealizedPosition(GeneratorPosition p) => p.Offset == 0;","tryCatchPattern":"try { generator.Remove(pos, count, true); }\ncatch (ArgumentException ex) when (ex.ParamName == \"position\")\n{\n    // re-derive a normalized position and retry\n}","preventionTips":["Always derive positions from GeneratorPositionFromIndex and check Offset before Remove/Recycle.","Verify the item is realized via ContainerFromIndex before removing."],"tags":["wpf","itemcontainergenerator","argument","generator-position"],"backgroundTag":"invalid-argument-value","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"}