dotnet/reactive · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException

Error message

ArgumentOutOfRangeException

What it means

ArgumentOutOfRangeException thrown by GroupBy(source, keySelector, capacity) when capacity is negative. Capacity is a hint for pre-allocating internal group storage and must be >= 0; the library treats a negative value as a caller bug and fails fast.

Solutions

  1. Pass a non-negative capacity, e.g. Math.Max(0, configuredCapacity).
  2. If capacity is unknown, use the overload without the capacity parameter.
  3. Clamp or validate any config-derived value before passing it.

Example fix

// before
var g = source.GroupBy(x => x.Key, expected - actual); // may be negative
// after
var g = source.GroupBy(x => x.Key, Math.Max(0, expected - actual));
Defensive patterns

Strategy: validation

Validate before calling

if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity), capacity, "capacity must be >= 0");
var groups = source.GroupBy(keySelector, capacity);

Type guard

static bool IsValidCapacity(int capacity) => capacity >= 0;

Try / catch

try { var g = source.GroupBy(k, capacity); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "capacity") { var g = source.GroupBy(k); }

Prevention

When it happens

Trigger: Calling source.GroupBy(keySelector, capacity) with capacity < 0, e.g. computing capacity from a subtraction or a config value that ended up negative (line 326 is the capacity check block).

Common situations: Deriving capacity from `max - min` where inputs were swapped; reading a sizing hint from appSettings where a sentinel -1 meant 'auto' but the API has no auto mode.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/23e29075c80dc244. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:326

        /// <param name="capacity">The initial number of elements that the underlying dictionary can contain.</param>
        /// <returns>A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        public static IObservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, int capacity)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (keySelector == null)
            {
                throw new ArgumentNullException(nameof(keySelector));
            }

            if (capacity < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(capacity));
            }

            return s_impl.GroupBy(source, keySelector, capacity);
        }

        /// <summary>
        /// Groups the elements of an observable sequence with the specified initial capacity according to a specified key selector function and comparer.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TKey">The type of the grouping key computed for each element in the source sequence.</typeparam>
        /// <param name="source">An observable sequence whose elements to group.</param>
        /// <param name="keySelector">A function to extract the key for each element.</param>
        /// <param name="capacity">The initial number of elements that the underlying dictionary can contain.</param>
        /// <param name="comparer">An equality comparer to compare keys with.</param>
        /// <returns>A sequence of observable groups, each of which corresponds to a unique key value, containing all elements that share that same key value.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="keySelector"/> or <paramref name="comparer"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity"/> is less than 0.</exception>
        public static IObservable<IGroupedObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IObservable<TSource> source, Func<TSource, TKey> keySelector, int capacity, IEqualityComparer<TKey> comparer)

View on GitHub (pinned to 94b5d5ab91)