dotnet/reactive · error · ArgumentOutOfRangeException
ArgumentOutOfRangeException(nameof(maxConcurrent))
Error message
ArgumentOutOfRangeException(nameof(maxConcurrent))
What it means
Observable.Merge(sources, maxConcurrent) throws ArgumentOutOfRangeException when maxConcurrent is less than or equal to zero. Concurrency limits of 0 or negative values are meaningless (at least one inner stream must be allowed), so the library rejects them eagerly after the null check on sources.
Solutions
- Pass a positive maxConcurrent value (>= 1), e.g. Math.Max(1, configuredLimit).
- If 0 means 'no limit', call the parameterless Merge() overload instead.
- Validate the config value at load time and fail with a clear message before building the pipeline.
Example fix
// before
var merged = streams.Merge(maxConcurrentFromConfig); // may be 0
// after
var merged = maxConcurrentFromConfig > 0
? streams.Merge(maxConcurrentFromConfig)
: streams.Merge(); // treat 0 as unlimited Defensive patterns
Strategy: validation
Validate before calling
if (maxConcurrent <= 0)
throw new ArgumentOutOfRangeException(nameof(maxConcurrent), "Must be greater than zero");
var merged = sources.Merge(maxConcurrent); Type guard
bool IsValidConcurrency(int max) => max > 0;
Try / catch
try { var merged = sources.Merge(maxConcurrent); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "maxConcurrent") { log.Error("maxConcurrent must be > 0, got {0}", maxConcurrent); throw; } Prevention
- Clamp configured limits with Math.Max(1, value).
- Do not use 0 to mean 'unlimited'; call the parameterless Merge overload instead.
- Validate config integers at load time, before pipeline construction.
When it happens
Trigger: Calling sources.Merge(0) or sources.Merge(-1); passing a computed limit from config (e.g. 'maxConcurrentConnections': 0) or an uninitialized int defaulting to 0.
Common situations: Config files where 0 was intended to mean 'unlimited' but the API expects a positive integer; parsing an empty/invalid setting into default(int) = 0; off-by-one in a derived limit.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/b224dde9eab3d37e.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.cs:494
/// <summary>
/// Merges elements from all inner observable sequences into a single observable sequence, limiting the number of concurrent subscriptions to inner sequences.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Observable sequence of inner observable sequences.</param>
/// <param name="maxConcurrent">Maximum number of inner observable sequences being subscribed to concurrently.</param>
/// <returns>The observable sequence that merges the elements of the inner sequences.</returns>
/// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="maxConcurrent"/> is less than or equal to zero.</exception>
public static IObservable<TSource> Merge<TSource>(this IObservable<IObservable<TSource>> sources, int maxConcurrent)
{
if (sources == null)
{
throw new ArgumentNullException(nameof(sources));
}
if (maxConcurrent <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxConcurrent));
}
return s_impl.Merge(sources, maxConcurrent);
}
/// <summary>
/// Merges elements from all observable sequences in the given enumerable sequence into a single observable sequence, limiting the number of concurrent subscriptions to inner sequences.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
/// <param name="sources">Enumerable sequence of observable sequences.</param>
/// <param name="maxConcurrent">Maximum number of observable sequences being subscribed to concurrently.</param>
/// <returns>The observable sequence that merges the elements of the observable sequences.</returns>
/// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="maxConcurrent"/> is less than or equal to zero.</exception>
public static IObservable<TSource> Merge<TSource>(this IEnumerable<IObservable<TSource>> sources, int maxConcurrent)
{
if (sources == null)
{View on GitHub (pinned to 94b5d5ab91)