dotnet/reactive · error · ArgumentOutOfRangeException

capacity

Error message

capacity

What it means

In the 6-argument GroupBy overload, a negative capacity throws ArgumentOutOfRangeException named 'capacity' (line 398). The message surface here shows only the parameter name, which is the framework's abbreviated rendering of the range violation. Capacity sizes the internal group map and must be non-negative.

Solutions

  1. Clamp before calling: Math.Max(0, capacity).
  2. Substitute a default positive capacity (e.g. 16) when the value is unknown or negative.
  3. Validate the config/input source and reject or correct negative values at load time.
  4. Log the raw source value to find where the negative number originates.

Example fix

// before
GroupBy(observer, sub, k, e, settings.InitialGroupCapacity, cmp); // can be -1
// after
var cap = Math.Max(16, settings.InitialGroupCapacity);
GroupBy(observer, sub, k, e, cap, cmp);
Defensive patterns

Strategy: validation

Validate before calling

if (capacity < 0) throw new ArgumentOutOfRangeException(nameof(capacity));
GroupBy(observer, subscription, keySelector, elementSelector, capacity, comparer);

Type guard

bool IsValidCapacity(int c) => c >= 0;

Try / catch

try { GroupBy(obs, sub, k, e, cap, cmp); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "capacity") { /* clamp value and retry */ }

Prevention

When it happens

Trigger: Calling GroupBy<TSource,TKey,TElement>(observer, subscription, keySelector, elementSelector, capacity < 0, comparer) — usually with capacity derived from config, user input, or arithmetic that can go negative.

Common situations: 'Unset' config sentinel values like -1 passed through; computed sizes such as maxItems - extra; deserialized settings where capacity was omitted and defaulted to a negative number.

Related errors


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

Appendix: source

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

                throw new ArgumentNullException(nameof(elementSelector));
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));

            return GroupBy(observer, subscription, keySelector, elementSelector, capacity, EqualityComparer<TKey>.Default);
        }

        public static (IAsyncObserver<TSource>, IAsyncDisposable) GroupBy<TSource, TKey, TElement>(IAsyncObserver<IGroupedAsyncObservable<TKey, TElement>> observer, IAsyncDisposable subscription, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, int capacity, IEqualityComparer<TKey> comparer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));
            if (elementSelector == null)
                throw new ArgumentNullException(nameof(elementSelector));
            if (capacity < 0)
                throw new ArgumentOutOfRangeException(nameof(capacity));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return GroupBy<TSource, TKey, TElement>(observer, subscription, x => new ValueTask<TKey>(keySelector(x)), x => new ValueTask<TElement>(elementSelector(x)), capacity, comparer);
        }

        public static (IAsyncObserver<TSource>, IAsyncDisposable) GroupBy<TSource, TKey>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, ValueTask<TKey>> keySelector)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (subscription == null)
                throw new ArgumentNullException(nameof(subscription));
            if (keySelector == null)
                throw new ArgumentNullException(nameof(keySelector));

            return GroupBy(observer, subscription, keySelector, int.MaxValue, EqualityComparer<TKey>.Default);
        }

View on GitHub (pinned to 94b5d5ab91)