dotnet/reactive · error · ArgumentNullException
source
Error message
source
What it means
Merge's public extension throws ArgumentNullException when the source observable of observables is null. Merge flattens a stream of inner streams into one; with no outer source there is nothing to subscribe. The check runs before Create builds the subscription pipeline.
Solutions
- Ensure the outer source is a valid IAsyncObservable<IAsyncObservable<TSource>> before calling Merge
- Check the preceding operator/factory in the chain for null returns
- If sources may be absent, default to AsyncObservable.Empty<IAsyncObservable<TSource>>()
Example fix
// before IAsyncObservable<IAsyncObservable<int>> sources = GetSources(); // returns null var merged = sources.Merge(); // after var merged = (sources ?? AsyncObservable.Empty<IAsyncObservable<int>>()).Merge();
Defensive patterns
Strategy: validation
Validate before calling
if (sources == null) throw new InvalidOperationException("Outer source for Merge must not be null"); Type guard
bool HasSource<T>(IAsyncObservable<T> s) => s is not null;
Try / catch
try { var merged = sources.Merge(); } catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* fall back to empty source */ } Prevention
- Verify upstream operators/factories never return null
- Default missing sources to AsyncObservable.Empty
- Chain Merge only from known-good producers
When it happens
Trigger: Calling nullSource.Merge<TSource>() — e.g. an IAsyncObservable<IAsyncObservable<T>> variable that is null because an upstream factory returned null.
Common situations: Chaining Merge after an operator that returned null; conditional pipeline construction leaving the source unassigned; deserialized/configured sources that failed to resolve.
Related errors
- observer
- Value cannot be null. (Parameter 'disposable1')
- Value cannot be null. (Parameter 'disposable2')
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'source')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/0203a799189aeeb1.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Merge.cs:18
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
// TODO: Add Merge with max concurrency and IEnumerable<T>-based overloads.
public static IAsyncObservable<TSource> Merge<TSource>(this IAsyncObservable<IAsyncObservable<TSource>> source)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return Create<TSource>(async observer =>
{
var (sink, cancel) = AsyncObserver.Merge(observer);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, cancel);
});
}
}
public partial class AsyncObserver
{
public static (IAsyncObserver<IAsyncObservable<TSource>>, IAsyncDisposable) Merge<TSource>(IAsyncObserver<TSource> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));View on GitHub (pinned to 94b5d5ab91)