dotnet/wpf · error · ArgumentException

SR.Format(SR.RemoveRequiresPositiveCount, count)

Error message

SR.Format(SR.RemoveRequiresPositiveCount, count)

What it means

ItemContainerGenerator.Remove/Recycle validates that the count of containers to remove is positive. Passing zero or a negative count makes the operation meaningless and throws ArgumentException with SR.RemoveRequiresPositiveCount.

Solutions

  1. Guard the call: only invoke Remove when count > 0.
  2. Fix range math so lastIndex >= firstIndex before computing count = lastIndex - firstIndex + 1.
  3. Skip the Remove call entirely for empty ranges instead of passing 0.

Example fix

// before
generator.Remove(position, count, true); // count may be 0

// after
if (count > 0)
    generator.Remove(position, count, true);
Defensive patterns

Strategy: validation

Validate before calling

if (count <= 0) return; // nothing to remove
generator.Remove(position, count, true);

Type guard

static bool IsValidRemoveCount(int c) => c > 0;

Try / catch

try { generator.Remove(pos, count, true); }
catch (ArgumentException ex) when (ex.ParamName == "count") { /* log empty/negative range */ }

Prevention

When it happens

Trigger: Calling Remove(position, 0, ...) or Remove(position, negativeCount, ...), typically from a loop that computed count as lastIndex-firstIndex when lastIndex < firstIndex.

Common situations: Custom virtualization code computing removal ranges from viewport math that produced an inverted or empty range; off-by-one errors when the range is empty.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/78be71aa1a46684f. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemContainerGenerator.cs:274

        }

        /// <summary>
        /// Remove generated elements.
        /// </summary>
        void IItemContainerGenerator.Remove(GeneratorPosition position, int count)
        {
            Remove(position, count, /*isRecycling = */ false);
        }

        /// <summary>
        /// Remove generated elements.
        /// </summary>
        private void Remove(GeneratorPosition position, int count, bool isRecycling)
        {
            if (position.Offset != 0)
                throw new ArgumentException(SR.Format(SR.RemoveRequiresOffsetZero, position.Index, position.Offset), nameof(position));
            if (count <= 0)
                throw new ArgumentException(SR.Format(SR.RemoveRequiresPositiveCount, count), nameof(count));

            if (_itemMap == null)
            {
                // ignore reentrant call (during RemoveAllInternal)
                Debug.Fail("Unexpected reentrant call to ICG.Remove");
                return;
            }

            int index = position.Index;
            ItemBlock block;

            // find the leftmost item to remove
            int offsetL = index;
            for (block = _itemMap.Next;  block != _itemMap;  block = block.Next)
            {
                if (offsetL < block.ContainerCount)
                    break;

View on GitHub (pinned to 81131a70a4)