dotnet/reactive · error · ArgumentNullException
nameof(onCompleted)
Error message
nameof(onCompleted)
What it means
The full Do overload forwards onNext, onError, and onCompleted notifications to a witness observer, and the onCompleted callback must be non-null so completion signals can be witnessed. The library throws ArgumentNullException at argument-validation time when onCompleted is null. Nothing is subscribed yet when this fires.
Solutions
- Pass a non-null onCompleted handler; use () => { } if completion should be ignored.
- If no completion handling is needed, use the single-action overloads like Do(observer, onNext) instead.
- Guard the callback variable for null before the call and substitute a no-op.
Example fix
// before
var observer = Do(src, OnNext, OnError, null);
// after
var observer = Do(src, OnNext, OnError, () => { }); Defensive patterns
Strategy: validation
Validate before calling
if (onCompleted == null) onCompleted = () => { };
var observed = Do(observer, onNext, onError, onCompleted); Type guard
bool IsValidHandler(Delegate d) => d is not null;
Try / catch
try
{
var observed = Do(observer, onNext, onError, onCompleted);
}
catch (ArgumentNullException ex) when (ex.ParamName == "onCompleted")
{
var observed = Do(observer, onNext, onError, () => { });
} Prevention
- Supply all three callbacks explicitly when using the full Do overload.
- Use the smaller Do overloads when you only need some handlers.
- Turn on nullable reference analysis to catch uninitialized delegate variables.
When it happens
Trigger: Calling Do<TSource>(observer, onNext, onError, onCompleted) (Do.cs:244) with null for the onCompleted argument.
Common situations: Developers assume completion handling is optional and omit it; code that synthesizes handlers from configuration where the completion hook is absent; copy-pasting a two-argument Do call and leaving the last argument empty.
Related errors
- nameof(onError)
- nameof(witness)
- threadFactory (Parameter 'threadFactory')
- action (Parameter 'action')
- comparer (Parameter 'comparer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/adead206aedeacbf.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Do.cs:244
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return Do(observer, Create<TSource>(_ => default, _ => default, onCompleted));
}
public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, Func<TSource, ValueTask> onNext, Func<Exception, ValueTask> onError, Func<ValueTask> onCompleted)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
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 Do(observer, Create(onNext, onError, onCompleted));
}
public static IAsyncObserver<TSource> Do<TSource>(IAsyncObserver<TSource> observer, IObserver<TSource> witness)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (witness == null)
throw new ArgumentNullException(nameof(witness));
return Create<TSource>(
async x =>
{
try
{
witness.OnNext(x);
}View on GitHub (pinned to 94b5d5ab91)