dotnet/reactive · error · ArgumentOutOfRangeException
ArgumentOutOfRangeException: capacity
Error message
ArgumentOutOfRangeException: capacity
What it means
The capacity-taking GroupByUntil overload requires a non-negative capacity (the maximum number of concurrently live groups held by the operator's internal map). A negative value was passed, so the library throws ArgumentOutOfRangeException immediately. This is a fail-fast guard against an obviously meaningless configuration value.
Solutions
- Pass 0 or a positive capacity; use int.MaxValue (the overload without capacity does this) for unlimited groups
- Clamp the value before calling: Math.Max(0, configuredCapacity)
- Fix the upstream configuration or computation that produced the negative number
Example fix
// before var res = source.GroupByUntil(k => k, g => g.Take(1), config.MaxGroups); // -1 when unset // after var res = source.GroupByUntil(k => k, g => g.Take(1), config.MaxGroups is int c && c >= 0 ? c : int.MaxValue);
Defensive patterns
Strategy: validation
Validate before calling
if (capacity < 0) throw new ArgumentException("capacity must be non-negative", nameof(capacity));
// or normalize: capacity = capacity is int c && c >= 0 ? c : int.MaxValue; Type guard
bool IsValidCapacity(int capacity) => capacity >= 0;
Try / catch
try { var res = source.GroupByUntil(keySelector, durationSelector, capacity); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "capacity") { /* fall back to int.MaxValue or a sane default */ } Prevention
- Translate 'unlimited' config sentinels (-1, 0?) to int.MaxValue at configuration load time
- Clamp numeric settings with Math.Max when reading them
- Validate settings at startup, not at query construction
When it happens
Trigger: Calling GroupByUntil(observer, subscription, keySelector, durationSelector, capacity) (GroupByUntil.cs:349) with capacity < 0, e.g. a computed limit that evaluated to -1 because a config value was missing or a subtraction underflowed.
Common situations: Reading a group-limit setting from configuration where the default is -1 meaning 'unset'; computing capacity from a collection size that came back empty; integer arithmetic returning a negative sentinel.
Related errors
- ArgumentNullException: durationSelector
- ArgumentNullException: observer
- ArgumentNullException: comparer
- throw new ArgumentOutOfRangeException(nameof(dueTime));
- ArgumentOutOfRangeException
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/581b6779f1ea3c2b.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/GroupByUntil.cs:360
throw new ArgumentNullException(nameof(durationSelector));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return GroupByUntil(observer, subscription, keySelector, durationSelector, int.MaxValue, comparer);
}
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, int capacity)
{
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 (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity));
return GroupByUntil(observer, subscription, keySelector, durationSelector, capacity, EqualityComparer<TKey>.Default);
}
public static ValueTask<(IAsyncObserver<TSource>, IAsyncDisposable)> GroupByUntil<TSource, TKey, TDuration>(IAsyncObserver<IGroupedAsyncObservable<TKey, TSource>> observer, IAsyncDisposable subscription, Func<TSource, TKey> keySelector, Func<IGroupedAsyncObservable<TKey, TSource>, IAsyncObservable<TDuration>> durationSelector, 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 (durationSelector == null)
throw new ArgumentNullException(nameof(durationSelector));
if (capacity < 0)
throw new ArgumentOutOfRangeException(nameof(capacity));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));View on GitHub (pinned to 94b5d5ab91)