dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'source')
Error message
Value cannot be null. (Parameter 'source')
What it means
The protected EventPatternSourceBaseInternal constructor requires a non-null source sequence (IAsyncObservable<EventPattern<TSender,TEventArgs>>) since it exposes that sequence as an event. A null source is rejected immediately with ArgumentNullException, as documented by the constructor's <exception> tag.
Solutions
- Pass a valid non-null IAsyncObservable as source.
- Fix the factory/producer that returned the null source.
- Guard in the derived factory before invoking the base constructor and throw a clearer error.
Example fix
// before
public MyEventPatternSource(IAsyncObservable<EventPattern<object, EventArgs>> source)
: base(source, Invoke) { }
// after
public MyEventPatternSource(IAsyncObservable<EventPattern<object, EventArgs>> source)
: base(source ?? throw new InvalidOperationException("source observable required"), Invoke) { } Defensive patterns
Strategy: validation
Validate before calling
if (source is null) throw new ArgumentNullException(nameof(source)); // then construct the derived EventPatternSourceBaseInternal with source
Type guard
static bool HasSource(IAsyncObservable<EventPattern<TSender,TEventArgs>>? s) => s is not null;
Try / catch
try { CreateEventPatternSource(source, invoke); }
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{ log.LogError("event-pattern source observable was null"); } Prevention
- Ensure observable factories (FromEventPattern-style helpers) never return null; throw instead.
- Order constructor arguments carefully in derived classes.
- Enable nullable reference types to catch null observables at compile time.
When it happens
Trigger: Calling the base constructor from a derived event-pattern class with a null source — e.g. FromEventPattern-style factory passing a null observable, or a chain like source.Where(...) that returned null.
Common situations: Implementing a custom event bridge class and passing an uninitialized observable field; an upstream factory method returning null; mis-ordered constructor arguments in a derived class.
Related errors
- Value cannot be null. (Parameter 'invokeHandler')
- Value cannot be null. (Parameter 'handler')
- Value cannot be null. (Parameter 'invoke')
- nameof(source)
- nameof(source)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/5b9890d2be51282b.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Internal/EventPatternSourceBaseInternal.cs:36
/// TODO: System.Reactive defines an EventPatternSourceBase. I (idg10) renamed this to EventPatternSourceBaseInternal to
/// avoid a conflict. Work out whether we could in fact just use the type defined in System.Reactive. It's not identical,
/// but perhaps it offers what we need.
/// </remarks>
internal abstract class EventPatternSourceBaseInternal<TSender, TEventArgs>
{
private readonly IAsyncObservable<EventPattern<TSender, TEventArgs>> _source;
private readonly Dictionary<Delegate, Stack<IAsyncDisposable>> _subscriptions;
private readonly Action<Action<TSender, TEventArgs>, /*object,*/ EventPattern<TSender, TEventArgs>> _invokeHandler;
/// <summary>
/// Creates a new event pattern source.
/// </summary>
/// <param name="source">Source sequence to expose as an event.</param>
/// <param name="invokeHandler">Delegate used to invoke the event for each element of the sequence.</param>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="invokeHandler"/> is null.</exception>
protected EventPatternSourceBaseInternal(IAsyncObservable<EventPattern<TSender, TEventArgs>> source, Action<Action<TSender, TEventArgs>, /*object,*/ EventPattern<TSender, TEventArgs>> invokeHandler)
{
_source = source ?? throw new ArgumentNullException(nameof(source));
_invokeHandler = invokeHandler ?? throw new ArgumentNullException(nameof(invokeHandler));
_subscriptions = new Dictionary<Delegate, Stack<IAsyncDisposable>>();
}
/// <summary>
/// Adds the specified event handler, causing a subscription to the underlying source.
/// </summary>
/// <param name="handler">Event handler to add. The same delegate should be passed to the Remove operation in order to remove the event handler.</param>
/// <param name="invoke">Invocation delegate to raise the event in the derived class.</param>
/// <exception cref="ArgumentNullException"><paramref name="handler"/> or <paramref name="invoke"/> is null.</exception>
protected void Add(Delegate handler, Action<TSender, TEventArgs> invoke)
{
if (handler == null)
throw new ArgumentNullException(nameof(handler));
if (invoke == null)
throw new ArgumentNullException(nameof(invoke));
var gate = new object();View on GitHub (pinned to 94b5d5ab91)