dotnet/reactive · error · ArgumentNullException
selector
Error message
selector
What it means
The Replay(source, selector, bufferSize, scheduler) overload throws ArgumentNullException because the selector delegate passed was null. The operator needs a non-null selector to build the multicast pipeline over the replay subject; a null selector would make the returned observable impossible to construct. The library validates all arguments eagerly at call time so failures surface at the call site rather than later during subscription.
Solutions
- Pass a non-null selector lambda, e.g. src => src.Select(...).Where(...).
- If the selector is variable, check it for null before calling Replay and handle the fallback explicitly.
- Verify the variable actually holds the composed delegate and was not reassigned to null elsewhere.
Example fix
// before IAsyncObservable<int> result = source.Replay(null, 10, Scheduler.Default.Async); // after IAsyncObservable<int> result = source.Replay(xs => xs.Select(x => x * 2), 10, Scheduler.Default.Async);
Defensive patterns
Strategy: validation
Validate before calling
if (selector is null) throw new InvalidOperationException("Replay selector must be provided");
// safe to call source.Replay(selector, bufferSize, scheduler); Type guard
bool HasSelector(Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>> f) => f is not null;
Try / catch
try { var r = source.Replay(selector, bufferSize, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "selector") { /* supply a default selector or fail fast */ } Prevention
- Always pass a lambda literal where possible instead of nullable delegate variables.
- Validate delegates at pipeline-configuration time, before building operators.
- Use required constructor/injection parameters for selectors.
When it happens
Trigger: Calling source.Replay(null, bufferSize, scheduler) or passing a variable/ternary/expression that evaluates to a null Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>>.
Common situations: Building the selector dynamically (e.g. from configuration or a dictionary of transforms) and the lookup fails returning null; refactoring code where the selector lambda was accidentally deleted; conditional pipelines that pass null when a feature flag is off.
Related errors
- ArgumentNullException: source
- durationSelector
- scheduler
- throw new ArgumentNullException(nameof(func));
- throw new ArgumentNullException(nameof(observer));
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/795b2842ccd13fa0.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Replay.cs:142
public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>> selector, int bufferSize)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
return Multicast(source, () => new SequentialReplayAsyncSubject<TSource>(bufferSize), selector);
}
public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>> selector, int bufferSize, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (bufferSize < 0)
throw new ArgumentOutOfRangeException(nameof(bufferSize));
if (scheduler == null)
throw new ArgumentNullException(nameof(scheduler));
return Multicast(source, () => new SequentialReplayAsyncSubject<TSource>(bufferSize, scheduler), selector);
}
public static IAsyncObservable<TResult> Replay<TSource, TResult>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TSource>, IAsyncObservable<TResult>> selector, TimeSpan window)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
if (window < TimeSpan.Zero)
throw new ArgumentOutOfRangeException(nameof(window));
return Multicast(source, () => new SequentialReplayAsyncSubject<TSource>(window), selector);View on GitHub (pinned to 94b5d5ab91)