dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'onCompleted')
Error message
Value cannot be null. (Parameter 'onCompleted')
What it means
The AnonymousObserver constructor throws ArgumentNullException when the onCompleted action is null. Along with onNext and onError, the completion callback must be a real delegate because Rx will invoke it when the sequence finishes; null is rejected at construction time.
Solutions
- Supply a real onCompleted action, e.g. () => Console.WriteLine("done")
- If completion is irrelevant, pass a no-op: () => { }
- Default the completion callback before subscribing
Example fix
// before var sub = source.Subscribe(x => Handle(x), ex => Log(ex), null); // after var sub = source.Subscribe(x => Handle(x), ex => Log(ex), () => Done());
Defensive patterns
Strategy: type-guard
Validate before calling
// C#
Action? onCompleted = ResolveCompleted();
if (onCompleted is null)
onCompleted = () => { };
var sub = source.Subscribe(x => Handle(x), ex => Log(ex), onCompleted); Type guard
bool HasCompleted(Action? a) => a is not null;
Try / catch
try { var sub = source.Subscribe(onNext, onError, onCompleted); }
catch (ArgumentNullException ex) when (ex.ParamName == "onCompleted")
{
// supply a no-op completion handler
} Prevention
- Use the Subscribe(onNext, onError) overload when completion is irrelevant
- Default completion fields to () => { }
- Never pass null positionally for the last Subscribe argument
When it happens
Trigger: Calling new AnonymousObserver<T>(onNext, onError, null) or source.Subscribe(onNext, onError, onCompleted: null), typically when the completion handler is fetched from a nullable delegate or omitted during refactor.
Common situations: UI subscriptions that only care about values and errors; dynamically composed handlers where the completed callback was never assigned; migration from Subscribe overloads that defaulted handlers to ones that require all three.
Related errors
- Value cannot be null. (Parameter 'onNext')
- Value cannot be null. (Parameter 'onError')
- observer
- observer
- observer
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/011bf3f6971a9e20.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/AnonymousObserver.cs:28
/// <typeparam name="T">The type of the elements in the sequence.</typeparam>
public sealed class AnonymousObserver<T> : ObserverBase<T>
{
private readonly Action<T> _onNext;
private readonly Action<Exception> _onError;
private readonly Action _onCompleted;
/// <summary>
/// Creates an observer from the specified <see cref="IObserver{T}.OnNext(T)"/>, <see cref="IObserver{T}.OnError(Exception)"/>, and <see cref="IObserver{T}.OnCompleted()"/> actions.
/// </summary>
/// <param name="onNext">Observer's <see cref="IObserver{T}.OnNext(T)"/> action implementation.</param>
/// <param name="onError">Observer's <see cref="IObserver{T}.OnError(Exception)"/> action implementation.</param>
/// <param name="onCompleted">Observer's <see cref="IObserver{T}.OnCompleted()"/> action implementation.</param>
/// <exception cref="ArgumentNullException"><paramref name="onNext"/> or <paramref name="onError"/> or <paramref name="onCompleted"/> is <c>null</c>.</exception>
public AnonymousObserver(Action<T> onNext, Action<Exception> onError, Action onCompleted)
{
_onNext = onNext ?? throw new ArgumentNullException(nameof(onNext));
_onError = onError ?? throw new ArgumentNullException(nameof(onError));
_onCompleted = onCompleted ?? throw new ArgumentNullException(nameof(onCompleted));
}
/// <summary>
/// Creates an observer from the specified <see cref="IObserver{T}.OnNext(T)"/> action.
/// </summary>
/// <param name="onNext">Observer's <see cref="IObserver{T}.OnNext(T)"/> action implementation.</param>
/// <exception cref="ArgumentNullException"><paramref name="onNext"/> is <c>null</c>.</exception>
public AnonymousObserver(Action<T> onNext)
: this(onNext, Stubs.Throw, Stubs.Nop)
{
}
/// <summary>
/// Creates an observer from the specified <see cref="IObserver{T}.OnNext(T)"/> and <see cref="IObserver{T}.OnError(Exception)"/> actions.
/// </summary>
/// <param name="onNext">Observer's <see cref="IObserver{T}.OnNext(T)"/> action implementation.</param>
/// <param name="onError">Observer's <see cref="IObserver{T}.OnError(Exception)"/> action implementation.</param>
/// <exception cref="ArgumentNullException"><paramref name="onNext"/> or <paramref name="onError"/> is <c>null</c>.</exception>View on GitHub (pinned to 94b5d5ab91)