dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

Materialize wraps an observer so that every OnNext/OnError/OnCompleted is surfaced as a Notification<TSource> value. The library eagerly validates that the downstream observer is not null and throws ArgumentNullException with parameter name 'observer' at the top of the factory method, before any subscription happens.

Solutions

  1. Pass a non-null IAsyncObserver<Notification<TSource>> instance to Materialize
  2. Check the factory/expression producing the observer for a code path that returns null
  3. If the observer may legitimately be absent, use AsyncObserver./* no-op */ observer or a stub implementation instead of null

Example fix

// before
var obs = GetObserverOrNull();
var m = AsyncObserver.Materialize<int>(obs); // throws if null
// after
var obs = GetObserverOrNull() ?? AsyncObserver.Create<Notification<int>>(async n => { });
var m = AsyncObserver.Materialize<int>(obs);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));
// or guard at call site:
System.Diagnostics.Debug.Assert(observer != null, "observer must be non-null before Materialize");

Type guard

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

Try / catch

try
{
    var materialized = AsyncObserver.Materialize(sourceObserver);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
    // supply a default observer or surface a configuration error
}

Prevention

When it happens

Trigger: Calling AsyncObserver.Materialize<TSource>(null), or passing a variable/chain expression that resolves to null (e.g. a factory method that returned null instead of an observer).

Common situations: Building custom operator pipelines where an observer is produced conditionally; refactoring code so a previously non-null observer field is no longer initialized; calling Materialize before wiring up the pipeline.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Materialize.cs:23

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<Notification<TSource>> Materialize<TSource>(this IAsyncObservable<TSource> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return Create<TSource, Notification<TSource>>(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.Materialize(observer)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> Materialize<TSource>(IAsyncObserver<Notification<TSource>> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return Create<TSource>(
                x => observer.OnNextAsync(Notification.CreateOnNext(x)),
                async ex =>
                {
                    await observer.OnNextAsync(Notification.CreateOnError<TSource>(ex)).ConfigureAwait(false);
                    await observer.OnCompletedAsync().ConfigureAwait(false);
                },
                async () =>
                {
                    await observer.OnNextAsync(Notification.CreateOnCompleted<TSource>()).ConfigureAwait(false);
                    await observer.OnCompletedAsync().ConfigureAwait(false);
                }
            );
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)