dotnet/wpf · error · ArgumentOutOfRangeException

SR.TableCollectionOutOfRange

Error message

SR.TableCollectionOutOfRange

What it means

TableTextElementCollectionInternal<T>.Insert validates that index is within [0, Size] before inserting. This ArgumentOutOfRangeException is thrown when the insertion position is negative or greater than the current item count. Unlike some collections, inserting exactly at Size (append position) is allowed.

Solutions

  1. Clamp the index: index = Math.Max(0, Math.Min(index, collection.Count)).
  2. Re-read Count immediately before inserting instead of caching an old value.
  3. Use Add when the intent is to append at the end.
  4. Guard with if (index >= 0 && index <= collection.Count) before calling.

Example fix

// before
collection.Insert(savedIndex, item); // savedIndex may be stale
// after
int index = Math.Min(savedIndex, collection.Count);
collection.Insert(Math.Max(0, index), item);
Defensive patterns

Strategy: validation

Validate before calling

index = Math.Max(0, Math.Min(index, collection.Count));
collection.Insert(index, item);

Type guard

static bool IsValidInsertIndex(ICollection c, int i) => i >= 0 && i <= c.Count;

Try / catch

try { collection.Insert(index, item); }
catch (ArgumentOutOfRangeException) { collection.Add(item); }

Prevention

When it happens

Trigger: Insert(index, item) with index < 0; index > Size, e.g. Insert(Count, ...) after items were removed (stale count), or inserting at a computed position derived from another collection's size.

Common situations: Inserting at a saved cursor position after the document changed, using an index from one collection on a different collection, and off-by-one errors when index was intended as 'append' but the collection shrank.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/documents/TableTextElementCollectionInternal.cs:104

        /// </exception>
        /// <remarks>
        /// If Count already equals Capacity, the capacity of the
        /// ContentElementCollection is increased before the new TItem is inserted.
        ///
        /// If index is equal to Count, TItem is added to the
        /// end of ContentElementCollection.
        ///
        /// The TItems that follow the insertion point move down to
        /// accommodate the new TItem. The indexes of the TItems that are
        /// moved are also updated.
        /// </remarks>
        public override void Insert(int index, TElementType item)
        {
            Version++;

            if (index < 0 || index > Size)
            {
                throw new ArgumentOutOfRangeException(SR.TableCollectionOutOfRange);
            }
            ArgumentNullException.ThrowIfNull(item);

            if (item.Parent != null)
            {
                throw new System.ArgumentException(SR.TableCollectionInOtherCollection);
            }

            Owner.InsertionIndex = index;
            if (index == Size)
            {
                item.RepositionWithContent(Owner.ContentEnd);
            }
            else
            {
                TElementType itemInsert = Items[index];
                TextPointer insertPosition = new TextPointer(itemInsert.ContentStart, -1);
                item.RepositionWithContent(insertPosition);

View on GitHub (pinned to 81131a70a4)