dotnet/reactive · error · ArgumentNullException
observer
Error message
observer
What it means
System.ArgumentNullException with ParamName 'observer' thrown by AsyncObserver.DistinctUntilChanged<TSource>(IAsyncObserver<TSource>) when the downstream observer is null. This is the observer-side factory variant used when composing custom async operators. A null observer cannot receive OnNextAsync/OnErrorAsync, so construction fails immediately.
Solutions
- Pass the actual non-null IAsyncObserver<TSource> from the enclosing subscription context.
- Check why the observer variable is null — it should originate from SubscribeSafeAsync/Subscribe plumbing.
- If writing an operator, propagate the observer argument rather than reconstructing it.
Example fix
// before
var obs = AsyncObserver.DistinctUntilChanged(downstreamObserver); // downstreamObserver was null
// after
if (downstreamObserver == null) throw new InvalidOperationException("observer not provided");
var obs = AsyncObserver.DistinctUntilChanged(downstreamObserver); Defensive patterns
Strategy: validation
Validate before calling
if (observer is null) throw new ArgumentNullException(nameof(observer)); var obs = AsyncObserver.DistinctUntilChanged(observer);
Type guard
bool IsValidObserver<TSource>(IAsyncObserver<TSource>? o) => o is not null;
Try / catch
try
{
var obs = AsyncObserver.DistinctUntilChanged(observer);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
throw new InvalidOperationException("Downstream observer was not supplied", ex);
} Prevention
- Only build observer chains from observers received via subscription callbacks
- Assert observer non-null at operator entry points in custom operators
- Keep observer plumbing arguments flowing; never hardcode null
When it happens
Trigger: Calling AsyncObserver.DistinctUntilChanged(null) inside a custom operator's subscription chain.
Common situations: Wrapping an observer obtained from a caller that passed null; building operator chains where an earlier stage handed back a null observer; tests passing null to exercise the factory.
Related errors
- ArgumentNullException(nameof(observer))
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'error')
- observer
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/c7a688118915a04c.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/DistinctUntilChanged.cs:95
throw new ArgumentNullException(nameof(source));
if (keySelector == null)
throw new ArgumentNullException(nameof(keySelector));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return Create(
source,
(keySelector, comparer),
static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.DistinctUntilChanged(observer, state.keySelector, state.comparer)));
}
}
public partial class AsyncObserver
{
public static IAsyncObserver<TSource> DistinctUntilChanged<TSource>(IAsyncObserver<TSource> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
return DistinctUntilChanged(observer, x => x, EqualityComparer<TSource>.Default);
}
public static IAsyncObserver<TSource> DistinctUntilChanged<TSource>(IAsyncObserver<TSource> observer, IEqualityComparer<TSource> comparer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (comparer == null)
throw new ArgumentNullException(nameof(comparer));
return DistinctUntilChanged(observer, x => x, comparer);
}
public static IAsyncObserver<TSource> DistinctUntilChanged<TSource, TKey>(IAsyncObserver<TSource> observer, Func<TSource, TKey> keySelector)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));View on GitHub (pinned to 94b5d5ab91)