dotnet/reactive · error · ArgumentNullException
nameof(witness)
Error message
nameof(witness)
What it means
In the witness-based Do overload, the IObserver<TSource> witness receives copies of the pipeline's notifications and must be non-null. The library throws ArgumentNullException for witness (Do.cs:254) if it is null, because there would be no side-effect observer to invoke. Validation occurs before any subscription work.
Solutions
- Pass a real witness observer; if diagnostics are optional, pass a no-op Observer stub instead of null.
- Skip the Do call entirely when no witness is available (condition the pipeline construction).
- Fix the factory/DI registration that was supposed to produce the witness observer.
Example fix
// before var decorated = Do(src, diagnosticsObserver); // null when monitoring disabled // after var decorated = diagnosticsObserver != null ? Do(src, diagnosticsObserver) : src;
Defensive patterns
Strategy: fallback
Validate before calling
var decorated = witness != null ? Do(observer, witness) : observer; // skip witness when unavailable
Type guard
static bool HasWitness<TSource>(IObserver<TSource>? w) => w is not null;
Try / catch
try
{
var decorated = Do(observer, witness);
}
catch (ArgumentNullException ex) when (ex.ParamName == "witness")
{
logger.LogWarning("No witness observer available; skipping Do side-effects");
var decorated = observer;
} Prevention
- Make the witness an explicit no-op stub rather than null when diagnostics are disabled.
- Register a default observer in DI so resolution never yields null.
- Conditionally compose the Do step instead of passing a nullable witness.
When it happens
Trigger: Calling Do<TSource>(observer, witness) with a null witness, e.g. a side-effect logger or monitoring observer that was never constructed or that a factory returned as null.
Common situations: Optional diagnostics observer resolved from DI/config is null in environments without monitoring enabled; test scaffolding that passes null instead of a stub observer; conditional instrumentation code that ends up passing nothing.
Related errors
- nameof(onError)
- nameof(onCompleted)
- Value cannot be null. (Parameter 'observer')
- ArgumentNullException(nameof(observer))
- Value cannot be null. (Parameter 'observer')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/9b0fe0c29c2dad2f.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Do.cs:254
{
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);
}
catch (Exception ex)
{
await observer.OnErrorAsync(ex).ConfigureAwait(false);
return;
}
await observer.OnNextAsync(x).ConfigureAwait(false);
},
async error =>
{View on GitHub (pinned to 94b5d5ab91)