dotnet/reactive · error · ArgumentNullException
conversion
Error message
conversion
What it means
The generic FromEvent<TDelegate, TEventArgs> requires a conversion function that turns Action<TEventArgs> into the target delegate type. When conversion is null the guard throws ArgumentNullException with ParamName "conversion" because the operator cannot bridge the framework event delegate to the handler pipeline.
Solutions
- Supply the conversion lambda, e.g. h => (EventHandler)h for EventHandler-based events.
- Use the non-generic FromEvent(Action<Action>, ...) overload if the event already accepts Action.
- Use FromEventPattern for EventHandler events, which supplies the conversion internally.
Example fix
// before var sub = AsyncRx.Observable.FromEvent<EventHandler, EventArgs>(null, h => src.Clicked += h, h => src.Clicked -= h); // after var sub = AsyncRx.Observable.FromEvent<EventHandler, EventArgs>(h => (EventHandler)((_, e) => h(e)), h => src.Clicked += h, h => src.Clicked -= h);
Defensive patterns
Strategy: validation
Validate before calling
if (conversion == null) conversion = h => (EventHandler)((_, e) => h(e));
Type guard
bool HasConversion<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion) => conversion != null;
Try / catch
try { var sub = FromEvent<TDelegate, TEventArgs>(conversion, add, remove); }
catch (ArgumentNullException ex) when (ex.ParamName == "conversion") { /* build a default conversion for the delegate type */ } Prevention
- Remember the generic FromEvent overload has no default conversion; the non-generic one does.
- For EventHandler-based events prefer FromEventPattern.
- Keep a small library of standard conversion lambdas per delegate type.
When it happens
Trigger: Calling FromEvent<TDelegate, TEventArgs>(null, addHandler, removeHandler), e.g. omitting the conversion lambda when subscribing to a non-Action event like EventHandler or a custom delegate.
Common situations: Subscribing to events whose delegate type is not Action<TEventArgs> (EventHandler, PropertyChangedEventHandler) and leaving the conversion slot empty; constructing the arguments dynamically where the converter string/delegate is null.
Related errors
- addHandler
- Value cannot be null. (Parameter 'predicate')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onCompletedAsync')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e22c4c87e0965d4a.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/FromEvent.cs:83
return FromEventCore<Action, Unit>(h => () => h(Unit.Default), addHandler, removeHandler, GetSchedulerForCurrentContext());
}
public static IAsyncObservable<Unit> FromEvent(Action<Action> addHandler, Action<Action> removeHandler, IAsyncScheduler scheduler)
{
if (addHandler == null)
throw new ArgumentNullException(nameof(addHandler));
if (removeHandler == null)
throw new ArgumentNullException(nameof(removeHandler));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return FromEventCore<Action, Unit>(h => () => h(Unit.Default), addHandler, removeHandler, scheduler);
}
public static IAsyncObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler)
{
if (conversion == null)
throw new ArgumentNullException(nameof(conversion));
if (addHandler == null)
throw new ArgumentNullException(nameof(addHandler));
if (removeHandler == null)
throw new ArgumentNullException(nameof(removeHandler));
return FromEventCore(conversion, addHandler, removeHandler, GetSchedulerForCurrentContext());
}
public static IAsyncObservable<TEventArgs> FromEvent<TDelegate, TEventArgs>(Func<Action<TEventArgs>, TDelegate> conversion, Action<TDelegate> addHandler, Action<TDelegate> removeHandler, IAsyncScheduler scheduler)
{
if (conversion == null)
throw new ArgumentNullException(nameof(conversion));
if (addHandler == null)
throw new ArgumentNullException(nameof(addHandler));
if (removeHandler == null)
throw new ArgumentNullException(nameof(removeHandler));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));View on GitHub (pinned to 94b5d5ab91)