dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'onCompleted')
Error message
Value cannot be null. (Parameter 'onCompleted')
What it means
The Do operator eagerly validates all arguments before returning the lazily-evaluated wrapped sequence. Passing null for the onCompleted action is rejected immediately with ArgumentNullException so the failure surfaces at the call site instead of during enumeration. The library requires every notification callback to be non-null, even ones that would otherwise do nothing.
Solutions
- Pass a no-op action `() => { }` for onCompleted if you do not need completion notification
- Use the Do(source, onNext) single-callback overload instead, which supplies the completion handler internally
- Ensure the callback variable is assigned before calling Do; guard with `?? new Action(() => { })`
- Check for null before the call: `if (onCompleted == null) onCompleted = () => {};`
Example fix
// before
var result = source.Do(x => Log(x), null);
// after
var result = source.Do(x => Log(x), () => { }); Defensive patterns
Strategy: validation
Validate before calling
if (source is null) throw new ArgumentNullException(nameof(source));
if (onNext is null) throw new ArgumentNullException(nameof(onNext));
if (onCompleted is null) onCompleted = () => { }; Type guard
static bool IsValidDoArgs<TSource>(IEnumerable<TSource>? s, Action<T>? onCompleted) => s is not null && onCompleted is not null;
Try / catch
try { var result = source.Do(x => Log(x), onCompleted!); ... }
catch (ArgumentNullException ex) when (ex.ParamName == "onCompleted") { Log("onCompleted callback missing; using no-op"); } Prevention
- Pass () => { } for callbacks you do not need rather than null
- Prefer the smaller Do overloads that supply internal no-op handlers
- Enable nullable reference types so null callbacks are caught at compile time
- Validate delegate arguments before composing LINQ pipelines
When it happens
Trigger: Calling Do<TSource>(source, onNext, onCompleted) with a null onCompleted action, e.g. `xs.Do(x => Console.WriteLine(x), null)` or passing a variable that was never assigned.
Common situations: Conditional callback assignment where only onError is populated; refactoring from the 2-argument overload to the 3-argument overload and forgetting the completion callback; deserializing callbacks from configuration where an optional handler resolves to null.
Related errors
- Value cannot be null. (Parameter 'onError')
- Thrown when onCompleted is null (ArgumentNullException…
- Thrown when source is null (ArgumentNullException, param…
- Thrown when observer is null (ArgumentNullException, param…
- Thrown when source is null (ArgumentNullException, param…
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/c9dbb64493a5a6e7.
Report an issue: GitHub.
Appendix: source
Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Do.cs:43
return DoCore(source, onNext, _ => { }, () => { });
}
/// <summary>
/// Lazily invokes an action for each value in the sequence, and executes an action for successful termination.
/// </summary>
/// <typeparam name="TSource">Source sequence element type.</typeparam>
/// <param name="source">Source sequence.</param>
/// <param name="onNext">Action to invoke for each element.</param>
/// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
/// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return DoCore(source, onNext, _ => { }, onCompleted);
}
/// <summary>
/// Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination.
/// </summary>
/// <typeparam name="TSource">Source sequence element type.</typeparam>
/// <param name="source">Source sequence.</param>
/// <param name="onNext">Action to invoke for each element.</param>
/// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
/// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));View on GitHub (pinned to 94b5d5ab91)