dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'observer')
Error message
Value cannot be null. (Parameter 'observer')
What it means
The comparer-overload of ToLookup validates all delegates up front. A null keySelector makes grouping impossible, so ArgumentNullException(nameof(keySelector)) is thrown immediately when composing the operator, before any elements flow.
Solutions
- Supply a non-null Func<TSource,ValueTask<TKey>> or Func<TSource,TKey> key selector
- Assert the key selector is resolved (e.g. from config/DI) before composing the pipeline
- Default to an identity selector x => x when grouping by the element itself
Example fix
// before var op = AsyncObservable.ToLookup(sink, (Func<Order, int>)null, x => x.Name, comparer); // after var op = AsyncObservable.ToLookup(sink, x => x.CustomerId, x => x.Name, comparer);
Defensive patterns
Strategy: validation
Validate before calling
if (observer is null || keySelector is null) throw new ArgumentException("observer and keySelector are required");
var op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer); Type guard
static bool CanGroup<TSource,TKey>(Func<TSource,ValueTask<TKey>> keySelector) => keySelector != null;
Try / catch
try
{
var op = AsyncObservable.ToLookup(observer, keySelector, valueSelector, comparer);
}
catch (ArgumentNullException ex) when (ex.ParamName == "keySelector")
{
keySelector = x => new ValueTask<TKey>(DefaultKey(x)); // fallback key
} Prevention
- Resolve key selectors from config/DI eagerly and assert non-null
- Use method groups (x => x.CustomerId) rather than nullable delegate fields
- Unit-test operator composition with all delegate arguments supplied
When it happens
Trigger: Calling AsyncObservable.ToLookup(observer, null, valueSelector, comparer) — 4-argument overload at ToLookup.cs:136 (the 3-argument overload's keySelector guard hits the same pattern at line 122).
Common situations: Key selector built from a lookup table or configuration map that was null; refactoring renamed a method leaving a null Func; generic helper forwarding a null selector.
Related errors
- Value cannot be null. (Parameter 'subscribeAsync')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onNextAsync')
- new ArgumentNullException(nameof(keySelector))
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/8d5c6f3877a0c402.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/AsyncObservableBase.cs:14
// 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.Threading.Tasks;
namespace System.Reactive
{
public abstract class AsyncObservableBase<T> : IAsyncObservable<T>
{
public async ValueTask<IAsyncDisposable> SubscribeAsync(IAsyncObserver<T> observer)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
var autoDetach = new AutoDetachAsyncObserver(observer);
var subscription = await SubscribeAsyncCore(autoDetach).ConfigureAwait(false);
await autoDetach.AssignAsync(subscription).ConfigureAwait(false);
return autoDetach;
}
protected abstract ValueTask<IAsyncDisposable> SubscribeAsyncCore(IAsyncObserver<T> observer);
private sealed class AutoDetachAsyncObserver : AsyncObserverBase<T>, IAsyncDisposable
{
private readonly IAsyncObserver<T> _observer;
private readonly object _gate = new();
private IAsyncDisposable _subscription;View on GitHub (pinned to 94b5d5ab91)