dotnet/reactive · error · ArgumentNullException
Argument cannot be null (Parameter name: source)
Error message
Argument cannot be null (Parameter name: source)
What it means
ForEachAsync(IAsyncObservable<TSource>, Action<TSource>, CancellationToken) throws ArgumentNullException because the source observable is null. ForEachAsync is an extension method, but extension methods can be invoked with a null receiver (including explicit static calls), so the null check names 'source'. Validation happens immediately, before the subscription work begins.
Solutions
- Ensure the source observable is created (e.g. AsyncObservable.Return/FromEvent/Empty) before iterating it.
- Guard: if (source == null) return Task.CompletedTask; when absence legitimately means 'nothing to observe'.
- Fix the producer that returns null so it returns AsyncObservable.Empty<TSource>() instead.
- If using an explicit static call, pass a real IAsyncObservable<TSource> instance.
Example fix
// before
var source = _registry.TryGet(key); // returns null when missing
await source.ForEachAsync(x => Handle(x));
// after
var source = _registry.TryGet(key);
if (source != null)
await source.ForEachAsync(x => Handle(x)); Defensive patterns
Strategy: validation
Validate before calling
if (source == null)
return Task.CompletedTask; // nothing to observe
return source.ForEachAsync(onNext, token); Type guard
static bool IsNonNullObservable<T>(IAsyncObservable<T> s) => s is not null;
Try / catch
try { await source.ForEachAsync(onNext, token); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* source factory returned null — treat as no data or rethrow with context */ } Prevention
- Make observable factories throw or return Empty, never null.
- Guard extension-method calls where the receiver may be null.
- Enable nullable reference types so null receivers are flagged.
When it happens
Trigger: Calling observable.ForEachAsync(onNext) where observable is null — e.g. a method that returns IAsyncObservable<T> and returned null, or an explicit AsyncObservable.ForEachAsync(null, action) call.
Common situations: Factory/DI methods that return null instead of an empty observable; caching a subscription source in a field that was never initialized; optional sources in configuration that were not created.
Related errors
- Argument cannot be null (Parameter name: onNext)
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'source')
- Value cannot be null.
- Value cannot be null. (Parameter 'observer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/9216dc2ad91a4bf7.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/ForEachAsync.cs:16
// 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.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource> onNext, CancellationToken token = default)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
return ForEachAsyncCore(source, (x, i) => { onNext(x); return Task.CompletedTask; }, token);
}
public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Task> onNext, CancellationToken token = default)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
return ForEachAsyncCore(source, (x, i) => onNext(x), token);
}
public static Task ForEachAsync<TSource>(this IAsyncObservable<TSource> source, Action<TSource, int> onNext, CancellationToken token = default)
{View on GitHub (pinned to 94b5d5ab91)