dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'onNext')
Error message
Value cannot be null. (Parameter 'onNext')
What it means
ArgumentNullException thrown by the three-handler Do<TSource> extension when the onNext expression (Expression<Func<TSource, Task>>) is null. All handler arguments become nodes of the query expression tree sent to the provider, so onNext is validated immediately after source. The message names 'onNext'.
Solutions
- Provide a no-op onNext: _ => Task.CompletedTask
- Use a Do overload that takes fewer handlers if onNext is genuinely unneeded
- Fix the handler factory to emit a completed-task lambda instead of null
- Assert handler non-nullness at the point handlers are constructed
Example fix
// before query.Do(null, OnError, OnDone); // after query.Do(_ => Task.CompletedTask, OnError, OnDone);
Defensive patterns
Strategy: validation
Validate before calling
if (onNext is null) onNext = _ => Task.CompletedTask;
Type guard
static bool HasNext<TSource>(Expression<Func<TSource, Task>>? h) => h is not null;
Try / catch
try { q = source.Do(onNext, onError, onCompleted); }
catch (ArgumentNullException ex) when (ex.ParamName == "onNext") { q = source.Do(_ => Task.CompletedTask, onError, onCompleted); } Prevention
- Supply no-op lambdas instead of null for unused handlers
- Map observer interfaces so no-op handlers become Task.CompletedTask, not null
- Code-review Do call sites for all three handler arguments
When it happens
Trigger: Calling Do(source, null, onError, onCompleted) — usually when only error/completion logging was wired and the per-item handler was left null, or a handler selector returned null.
Common situations: Telemetry taps where item-level handling is optional; refactors that removed the body of onNext; mapping code from an observer interface where onNext was a no-op represented as null.
Related errors
- Value cannot be null. (Parameter 'onCompleted')
- Value cannot be null. (Parameter 'onError')
- Value cannot be null. (Parameter 'selector')
- 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/159c7ccc4936a841.
Report an issue: GitHub.
Appendix: source
Thrown at Ix.NET/Source/System.Interactive.Async.Providers/System/Linq/AsyncQueryableEx.Generated.cs:1076
throw new ArgumentNullException(nameof(onError));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return source.Provider.CreateQuery<TSource>(Expression.Call(Do__TSource__4__1(typeof(TSource)), source.Expression, onNext, onError, onCompleted));
}
private static MethodInfo? s_Do__TSource__4__2;
private static MethodInfo Do__TSource__4__2(Type TSource) =>
(s_Do__TSource__4__2 ??
(s_Do__TSource__4__2 = new Func<IAsyncQueryable<object>, Expression<Func<object, Task>>, Expression<Func<Exception, Task>>, Expression<Func<Task>>, IAsyncQueryable<object>>(Do<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
public static IAsyncQueryable<TSource> Do<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, Task>> onNext, Expression<Func<Exception, Task>> onError, Expression<Func<Task>> onCompleted)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
if (onError == null)
throw new ArgumentNullException(nameof(onError));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return source.Provider.CreateQuery<TSource>(Expression.Call(Do__TSource__4__2(typeof(TSource)), source.Expression, onNext, onError, onCompleted));
}
private static MethodInfo? s_Expand__TSource__2__0;
private static MethodInfo Expand__TSource__2__0(Type TSource) =>
(s_Expand__TSource__2__0 ??
(s_Expand__TSource__2__0 = new Func<IAsyncQueryable<object>, Expression<Func<object, CancellationToken, ValueTask<IAsyncEnumerable<object>>>>, IAsyncQueryable<object>>(Expand<object>).GetMethodInfo()!.GetGenericMethodDefinition())).MakeGenericMethod(TSource);
public static IAsyncQueryable<TSource> Expand<TSource>(this IAsyncQueryable<TSource> source, Expression<Func<TSource, CancellationToken, ValueTask<IAsyncEnumerable<TSource>>>> selector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));View on GitHub (pinned to 94b5d5ab91)