dotnet/wpf · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(nameof(oldList));

Error message

throw new ArgumentOutOfRangeException(nameof(oldList));

What it means

ThreeItemList.Promote(FrugalListBase<T> oldList) moves data from a smaller storage variant into this three-slot list. After copying entries, a switch on oldCount handles 1/2/3 items; any other count falls into default and throws ArgumentOutOfRangeException named 'oldList'. This means the old list reported a Count the three-item variant cannot classify — an internal invariant violation (count < 0 or > 3, or a count that should have taken the 'target too small' branch).

Solutions

  1. Ensure Promote is only called with oldList variants whose Count fits the target (0..3 for ThreeItemList).
  2. Check oldList.Count before promoting: if it exceeds the target capacity, use the larger variant (SixItemList/ArrayItemList) instead.
  3. If you subclass FrugalListBase, keep Count accurate and consistent with the number of stored entries.
  4. Reproducible outside custom code? File a dotnet/wpf bug; this is an internal invariant failure.

Example fix

// before
threeList.Promote(sixItemListWithCount4); // count 4 hits default case
// after
if (sixItemListWithCount4.Count <= 3)
{
    threeList.Promote(sixItemListWithCount4);
}
else
{
    var bigger = new ArrayItemList<T>(sixItemListWithCount4);
    bigger.Promote(sixItemListWithCount4);
}
Defensive patterns

Strategy: validation

Validate before calling

if (oldList is null) throw new ArgumentNullException(nameof(oldList));
if (oldList.Count is < 0 or > 3) throw new InvalidOperationException("Source count not promotable into ThreeItemList");
target.Promote(oldList);

Type guard

bool CanPromoteToThreeItem<T>(FrugalListBase<T> src) => src is { Count: >= 0 and <= 3 };

Try / catch

try { target.Promote(oldList); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "oldList")
{
    target = new ArrayItemList<T>(oldList.Count);
    target.Promote(oldList);
}

Prevention

When it happens

Trigger: Promote is called with an oldList whose Count is outside {0,1,2,3} while this list is large enough (Count >= oldCount), e.g. a corrupt/oversized FrugalListBase implementation, or a SixItemList passed to a ThreeItemList.Promote with 4+ items yet claiming to fit.

Common situations: Seen in WPF property-value caching when the effective-values storage is promoted through the FrugalList/FrugalObjectList variant chain; arises from internal bugs or reflection misuse, not typical application code.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Utility/FrugalList.cs:606

                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        SetAt(2, oldList.EntryAt(2));
                        break;

                    case 2:
                        SetAt(0, oldList.EntryAt(0));
                        SetAt(1, oldList.EntryAt(1));
                        break;

                    case 1:
                        SetAt(0, oldList.EntryAt(0));
                        break;

                    case 0:
                        break;

                    default:
                        throw new ArgumentOutOfRangeException(nameof(oldList));
                }
            }
            else
            {
                // this list is smaller than oldList
                throw new ArgumentException(SR.Format(SR.FrugalList_TargetMapCannotHoldAllData, oldList.ToString(), this.ToString()), nameof(oldList));
            }
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(SingleItemList<T> oldList)
        {
            SetCount(oldList.Count);
            SetAt(0, oldList.EntryAt(0));
        }

        // Class specific implementation to avoid virtual method calls and additional logic
        public void Promote(ThreeItemList<T> oldList)

View on GitHub (pinned to 81131a70a4)