dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

AsyncObserver.Contains(observer, element) throws ArgumentNullException because the downstream bool observer is null. This library validates all observer arguments eagerly at operator construction so subscription failures surface at the call site rather than later inside the async pipeline. Passing null here means the Contains operator would have nowhere to emit its result.

Solutions

  1. Pass a non-null IAsyncObserver<bool> (e.g. the observer received in your Subscribe delegate) to AsyncObserver.Contains.
  2. If you have no downstream observer, create one via AsyncObserver.Create or subscribe through AsyncObservable.Contains instead of calling the observer factory directly.
  3. Check any intermediate factory method that supplies the observer for accidental null returns.

Example fix

// before
var op = AsyncObserver.Contains<int>(null, 42);
// after
await AsyncObservable.Contains(source, 42).ForEachAsync(x => Console.WriteLine(x));
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));

Type guard

static bool IsValidObserver<T>(IAsyncObserver<T> o) => o is not null;

Try / catch

try { var op = AsyncObserver.Contains(observer, element); } catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* supply a valid observer or abort composition */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.Contains<TSource>(null, someElement) directly, or composing custom operator pipelines where a downstream observer variable was never initialized before being threaded into Contains.

Common situations: Hand-rolled operator composition in custom async Rx pipelines; a factory method returning null observer; refactoring that removed observer initialization; wiring observers conditionally and hitting a path where none was assigned.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Contains.cs:41

        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return CreateAsyncObservable<bool>.From(
                source,
                (element, comparer),
                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.Contains(observer, state.element, state.comparer)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> Contains<TSource>(IAsyncObserver<bool> observer, TSource element)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return Contains(observer, element, EqualityComparer<TSource>.Default);
        }

        public static IAsyncObserver<TSource> Contains<TSource>(IAsyncObserver<bool> observer, TSource element, IEqualityComparer<TSource> comparer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (comparer == null)
                throw new ArgumentNullException(nameof(comparer));

            return Create<TSource>(
                async x =>
                {
                    var equals = false;
                    try
                    {
                        equals = comparer.Equals(x, element);

View on GitHub (pinned to 94b5d5ab91)