dotnet/wpf · error · ArgumentOutOfRangeException

SR.ItemCollectionRemoveArgumentOutOfRange

Error message

SR.ItemCollectionRemoveArgumentOutOfRange

What it means

CompositeCollection.RemoveAt validates the index before removing. If removeIndex does not point at a valid item in the composite list (out of the range covering all contained collections and the private items list), it throws ArgumentOutOfRangeException with ItemCollectionRemoveArgumentOutOfRange.

Solutions

  1. Validate 0 <= index && index < compositeCollection.Count before calling RemoveAt
  2. Remove items by reference where possible, or recompute the composite index
  3. Avoid removing inside a forward loop; iterate backwards or re-fetch Count each iteration

Example fix

// before
composite.RemoveAt(innerIndex); // index from inner collection
// after
if (index >= 0 && index < composite.Count)
    composite.RemoveAt(index);
Defensive patterns

Strategy: validation

Validate before calling

bool canRemoveAt(CompositeCollection c, int i) => i >= 0 && i < c.Count;

Type guard

bool TryRemoveAt(CompositeCollection c, int i, out Exception err) { err = null; if (i < 0 || i >= c.Count) { err = new ArgumentOutOfRangeException(nameof(i)); return false; } return true; }

Try / catch

try { composite.RemoveAt(index); } catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "removeIndex") { /* refresh index and retry or log */ }

Prevention

When it happens

Trigger: Calling compositeCollection.RemoveAt(i) where i >= Count or i < 0; stale index capture before the composite shrank; index computed against the inner collection instead of the composite.

Common situations: Iterating a CompositeCollection while removing items without adjusting indices; removing by an index obtained from an inner ObservableCollection's position rather than the composite's flattened index space.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Data/CompositeCollection.cs:242

        public void RemoveAt(int removeIndex)
        {
            if ((0 <= removeIndex) && (removeIndex < Count))
            {
                object removedItem = this[removeIndex];

                CollectionContainer cc = removedItem as CollectionContainer;
                if (cc != null)
                {
                    RemoveCollectionContainer(cc);
                }

                InternalList.RemoveAt(removeIndex);

                OnCollectionChanged(NotifyCollectionChangedAction.Remove, removedItem, removeIndex);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(removeIndex),
                            SR.ItemCollectionRemoveArgumentOutOfRange);
            }
        }


        /// <summary>
        /// Create a new view on this collection [Do not call directly].
        /// </summary>
        /// <remarks>
        /// Normally this method is only called by the platform's view manager,
        /// not by user code.
        /// </remarks>
        ICollectionView ICollectionViewFactory.CreateView()
        {
            return new CompositeCollectionView(this);
        }

        #endregion Public Methods

View on GitHub (pinned to 81131a70a4)