dotnet/reactive · error · ArgumentNullException
selector
Error message
selector
What it means
Expand(source, selector, scheduler) requires a non-null selector Func<TSource, IObservable<TSource>> that recursively expands each element. A null selector throws ArgumentNullException synchronously at the call site. The selector is the core of the operator; without it no expansion can be defined.
Solutions
- Provide a valid selector before calling Expand
- If expansion is optional, use the source directly (or Observable.Empty chains) instead of a null selector
- Validate DI/config-provided delegates for null at composition time
Example fix
// before var expanded = source.Expand(expansionStrategy, Scheduler.Default); // strategy null // after var expanded = source.Expand(expansionStrategy ?? (x => Observable.Empty<Node>()), Scheduler.Default);
Defensive patterns
Strategy: validation
Validate before calling
if (selector == null) throw new ArgumentNullException(nameof(selector), "Expand requires a non-null selector.");
Type guard
bool IsValidSelector<TSource>(Func<TSource, IObservable<TSource>> f) => f is not null;
Try / catch
try { var expanded = source.Expand(selector, scheduler); }
catch (ArgumentNullException ex) when (ex.ParamName == "selector") { log.Error("Expand selector was null", ex); } Prevention
- Provide a default expansion strategy (e.g. return Empty) for optional behavior
- Verify reflection/config-resolved delegates before use
- Keep selector lambdas inline when they are not meant to be optional
When it happens
Trigger: Passing a null selector lambda — commonly an optional strategy delegate that was never assigned, or a method group built via reflection that returned null.
Common situations: Pluggable expansion strategies in tests left null, config-selected delegates that fail to resolve, refactoring that removed the selector body but kept the null variable.
Related errors
- iteratorMethod
- source
- Value cannot be null. (Parameter 'selector')
- Value cannot be null. (Parameter 'conversion')
- Value cannot be null. (Parameter 'source8')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/e31671a5be84617d.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/ObservableEx.cs:82
/// Expands an observable sequence by recursively invoking selector, using the specified scheduler to enumerate the queue of obtained sequences.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <param name="scheduler">Scheduler on which to perform the expansion by enumerating the internal queue of obtained sequences.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> or <paramref name="scheduler"/> is null.</exception>
[Experimental]
public static IObservable<TSource> Expand<TSource>(this IObservable<TSource> source, Func<TSource, IObservable<TSource>> selector, IScheduler scheduler)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (selector == null)
{
throw new ArgumentNullException(nameof(selector));
}
if (scheduler == null)
{
throw new ArgumentNullException(nameof(scheduler));
}
return s_impl.Expand(source, selector, scheduler);
}
/// <summary>
/// Expands an observable sequence by recursively invoking selector.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence and each of the recursively expanded sources obtained by running the selector function.</typeparam>
/// <param name="source">Source sequence with the initial elements.</param>
/// <param name="selector">Selector function to invoke for each produced element, resulting in another sequence to which the selector will be invoked recursively again.</param>
/// <returns>An observable sequence containing all the elements produced by the recursive expansion.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="selector"/> is null.</exception>View on GitHub (pinned to 94b5d5ab91)