dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

This ToLookup overload (observer, keySelector, valueSelector, comparer) first validates the downstream observer. A null observer means there is no destination to push the resulting ILookup notifications to, so the operator throws ArgumentNullException(nameof(observer)) synchronously before returning the pipeline.

Solutions

  1. Pass a valid IAsyncObserver<ILookup<TKey,TValue>> as the first argument
  2. Check that the observer-producing expression actually returns non-null before composing
  3. Create the observer with the library's observer factory APIs instead of passing null

Example fix

// before
var op = AsyncObservable.ToLookup(null, x => x.Key, x => x.Value, comparer);
// after
var sink = AsyncObserver.Create<ILookup<int, string>>(...);
var op = AsyncObservable.ToLookup(sink, x => x.Key, x => x.Value, comparer);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));
// then compose:
var op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer);

Type guard

static bool HasSink<T>(IAsyncObserver<T> o) => o != null;

Try / catch

try
{
    var op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer);
}
catch (ArgumentNullException ex) when (ex.ParamName == "observer")
{
    // create/attach a valid observer before composing
}

Prevention

When it happens

Trigger: Calling AsyncObservable.ToLookup(null, keySelector, valueSelector, comparer) — 4-argument overload at ToLookup.cs:134.

Common situations: A downstream observer variable not yet initialized; wiring pipelines where the observer is produced by another factory that returned null; constructor-injected observer that was never provided.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/AsyncObservable.cs:21

// See the LICENSE file in the project root for more information. 

using System.Threading.Tasks;

namespace System.Reactive
{
    public class AsyncObservable<T> : AsyncObservableBase<T>
    {
        private readonly Func<IAsyncObserver<T>, ValueTask<IAsyncDisposable>> _subscribeAsync;

        public AsyncObservable(Func<IAsyncObserver<T>, ValueTask<IAsyncDisposable>> subscribeAsync)
        {
            _subscribeAsync = subscribeAsync ?? throw new ArgumentNullException(nameof(subscribeAsync));
        }

        protected override ValueTask<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<T> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return _subscribeAsync(observer);
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)