dotnet/reactive · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException: capacity

Error message

ArgumentOutOfRangeException: capacity

What it means

GroupBy(source, keySelector, capacity, comparer) throws ArgumentOutOfRangeException named 'capacity' when capacity is negative. The capacity parameter presets group storage and must be >= 0; the check runs before comparer validation and pipeline creation.

Solutions

  1. Clamp to non-negative: Math.Max(0, capacity) before the call.
  2. Correct the configuration/computation producing the negative value.
  3. Use the overload without capacity when no sizing hint is needed.

Example fix

// before
var groups = source.GroupBy(x => x.Key, settings.GroupCapacity, comparer); // -1 possible
// after
var capacity = settings.GroupCapacity < 0 ? 0 : settings.GroupCapacity;
var groups = source.GroupBy(x => x.Key, capacity, comparer);
Defensive patterns

Strategy: validation

Validate before calling

if (capacity < 0) throw new InvalidOperationException("capacity must be >= 0");
var safeCapacity = Math.Max(0, capacity);

Type guard

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

Try / catch

try { var groups = source.GroupBy(keySelector, capacity, comparer); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "capacity") { log.LogError(ex, "GroupBy capacity was negative"); throw; }

Prevention

When it happens

Trigger: Calling GroupBy(source, keySelector, negativeCapacity, comparer) — capacity parsed from config as -1 sentinel, computed from empty collections, or an int field defaulting to -1.

Common situations: Configuration with placeholder negative values; arithmetic underflow from Count - 1 on empty sequences; API defaults conflated with 'unset' sentinels.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupBy.cs:64

            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));

            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(
                source,
                (keySelector, capacity),
                static (source, state, observer) => GroupByCore(source, observer, (o, d) => AsyncObserver.GroupBy(o, d, state.keySelector, state.capacity)));
        }

        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TSource>> GroupBy<TSource, TKey>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, int capacity, IEqualityComparer<TKey> comparer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return CreateAsyncObservable<IGroupedAsyncObservable<TKey, TSource>>.From(
                source,
                (keySelector, capacity, comparer),
                static (source, state, observer) => GroupByCore(source, observer, (o, d) => AsyncObserver.GroupBy(o, d, state.keySelector, state.capacity, state.comparer)));
        }

        public static IAsyncObservable<IGroupedAsyncObservable<TKey, TElement>> GroupBy<TSource, TKey, TElement>(this IAsyncObservable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (elementSelector == null)
                throw new ArgumentNullException(nameof(elementSelector));

View on GitHub (pinned to 94b5d5ab91)