dotnet/reactive · error · ArgumentNullException
observer
Error message
observer
What it means
ObservableBase<T>.Subscribe is the base subscription entry point that wraps the observer in an AutoDetachObserver. It throws ArgumentNullException for 'observer' when a null IObserver<T> is passed. The check occurs before scheduling so the error points at the caller's subscription.
Solutions
- Pass a fully constructed observer instance to Subscribe
- Use delegate-based Subscribe(onNext/onError/onCompleted) overloads which build the observer for you
- Null-check the observer variable before subscribing
Example fix
// before
IObserver<int> observer = _observers.TryGet(id); // may be null
observable.Subscribe(observer);
// after
var observer = _observers.TryGet(id) ?? new AnonymousObserver<int>(x => {}, e => {}, () => {});
observable.Subscribe(observer); Defensive patterns
Strategy: validation
Validate before calling
if (observer == null) throw new InvalidOperationException("observer is not initialized"); Try / catch
try { observable.Subscribe(observer); } catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* create a valid observer and resubscribe */ } Prevention
- Assign observer fields before subscribing
- Prefer Subscribe(onNext, onError, onCompleted) so Rx builds the observer
When it happens
Trigger: Calling observable.Subscribe(null) where the concrete observable derives from ObservableBase<T> (ObservableBase.cs:26) — the observer argument is null.
Common situations: Passing a custom IObserver<T> implementation stored in a field that was never assigned; an observer created by a factory that returned null; incorrect overload selection leading to a null first argument.
Related errors
- nameof(onError)
- nameof(onCompleted)
- nameof(witness)
- threadFactory (Parameter 'threadFactory')
- action (Parameter 'action')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/d5efaa3e60dc03c8.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/ObservableBase.cs:30
/// <remarks>
/// If you don't need a named type to create an observable sequence (i.e. you rather need
/// an instance rather than a reusable type), use the Observable.Create method to create
/// an observable sequence with specified subscription behavior.
/// </remarks>
/// <typeparam name="T">The type of the elements in the sequence.</typeparam>
public abstract class ObservableBase<T> : IObservable<T>
{
/// <summary>
/// Subscribes the given observer to the observable sequence.
/// </summary>
/// <param name="observer">Observer that will receive notifications from the observable sequence.</param>
/// <returns>Disposable object representing an observer's subscription to the observable sequence.</returns>
/// <exception cref="ArgumentNullException"><paramref name="observer"/> is <c>null</c>.</exception>
public IDisposable Subscribe(IObserver<T> observer)
{
if (observer == null)
{
throw new ArgumentNullException(nameof(observer));
}
var autoDetachObserver = new AutoDetachObserver<T>(observer);
if (CurrentThreadScheduler.IsScheduleRequired)
{
//
// Notice we don't protect this piece of code using an exception handler to
// redirect errors to the OnError channel. This call to Schedule will run the
// trampoline, so we'd be catching all exceptions, including those from user
// callbacks that happen to run there. For example, consider:
//
// Observable.Return(42, Scheduler.CurrentThread)
// .Subscribe(x => { throw new Exception(); });
//
// Here, the OnNext(42) call would be scheduled on the trampoline, so when we
// return from the scheduled Subscribe call, the CurrentThreadScheduler moves
// on to invoking this work item. Too much of protection here would cause theView on GitHub (pinned to 94b5d5ab91)