dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'observer')
Error message
Value cannot be null. (Parameter 'observer')
What it means
AsyncObserver.Range(observer, start, count) (and its scheduler overload) validates that the target IAsyncObserver<int> is non-null before scheduling value emission. A null observer throws ArgumentNullException naming 'observer'. The observer is the sink that receives the generated values, so the operation cannot proceed without it.
Solutions
- Pass a valid IAsyncObserver<int> implementation (e.g. from CreateSubscribeAsync or an AsyncObserver helper).
- If you only need the sequence, use AsyncObservable.Range(start, count) which wires the observer for you.
- Check the code path that produced the observer reference; fix why it is null.
- Add a non-null assertion/guard in your operator before delegating to AsyncObserver.Range.
Example fix
// before
await AsyncObserver.Range(observer, 0, 10); // observer is null
// after
if (observer == null) throw new InvalidOperationException("observer not initialized");
await AsyncObserver.Range(observer, 0, 10); Defensive patterns
Strategy: validation
Validate before calling
if (observer == null) throw new ArgumentNullException(nameof(observer));
Type guard
static bool IsValidObserver(IAsyncObserver<int> observer) => observer is not null;
Try / catch
try { await AsyncObserver.Range(observer, start, count); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* initialize or substitute observer */ } Prevention
- Prefer AsyncObservable.Range over the low-level AsyncObserver API.
- Assert observer non-null in your operator before delegating.
- Avoid lazy initialization patterns that can leave the observer null.
- Keep observer creation and subscription in the same code path.
When it happens
Trigger: Calling AsyncObserver.Range(null, 0, 10) directly; passing an observer variable that was never assigned, or the result of a factory/pipe that returned null; also triggered via the 4-argument overload with a null observer (the check runs before count/scheduler checks).
Common situations: Writing custom async observable operators that forward an observer parameter which is null; misusing the low-level AsyncObserver API instead of AsyncObservable.Range; test code constructing observers lazily and passing null on a failure path.
Related errors
- Value cannot be null. (Parameter 'func')
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'source9')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'onNext')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/5065714c987f53a9.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Range.cs:38
public static IAsyncObservable<int> Range(int start, int count, IAsyncScheduler scheduler)
{
if (count < 0 || ((long)start) + count - 1 > int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(count));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Create<int>(observer => AsyncObserver.Range(observer, start, count, scheduler));
}
}
public partial class AsyncObserver
{
public static ValueTask<IAsyncDisposable> Range(IAsyncObserver<int> observer, int start, int count) => Range(observer, start, count, TaskPoolAsyncScheduler.Default);
public static ValueTask<IAsyncDisposable> Range(IAsyncObserver<int> observer, int start, int count, IAsyncScheduler scheduler)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (count < 0 || ((long)start) + count - 1 > int.MaxValue)
throw new ArgumentOutOfRangeException(nameof(count));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return scheduler.ScheduleAsync(async ct =>
{
if (ct.IsCancellationRequested)
return;
for (int i = start, end = start + count - 1; i <= end && !ct.IsCancellationRequested; i++)
{
await observer.OnNextAsync(i).RendezVous(scheduler, ct);
}
if (ct.IsCancellationRequested)
return;
View on GitHub (pinned to 94b5d5ab91)