dotnet/reactive · error · ArgumentNullException
throw new ArgumentNullException(nameof(selector))
Error message
throw new ArgumentNullException(nameof(selector))
What it means
QbservableEx.Expand(source, selector) requires the expansion function as an Expression<Func<TSource, IObservable<TSource>>> so it can be embedded in the queryable expression tree. A null selector throws ArgumentNullException named 'selector'. Delegates are not acceptable here because remote query providers must inspect the expression.
Solutions
- Supply an expression lambda, e.g. x => Observable.Return(x), typed as Expression<Func<TSource, IObservable<TSource>>>
- Skip Expand when no expansion rule exists instead of passing null
- Fix the expression factory that returned null
Example fix
// before source.Expand(selector); // selector is null // after Expression<Func<TSource, IObservable<TSource>>> selector = x => Observable.Return(x); source.Expand(selector);
Defensive patterns
Strategy: validation
Validate before calling
if (selector == null)
throw new InvalidOperationException("Expand selector expression is required"); Type guard
bool HasSelector<T>(Expression<Func<T, IObservable<T>>> s) => s is not null;
Try / catch
try
{
var query = source.Expand(selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "selector")
{
logger.LogError(ex, "Expand selector was null");
} Prevention
- Pass expression lambdas directly to Expand instead of stored nullable lambdas
- Treat a missing expansion rule as a skip-the-operator condition, not null
- Verify Func vs Expression types when refactoring operator signatures
When it happens
Trigger: Calling source.Expand(null) — selector held in a nullable variable, conditionally assigned lambda, or produced by a builder that returned null.
Common situations: Config-driven operators where the expansion rule was not configured; refactoring that removed the lambda but kept the call; passing a Func where an Expression was expected and a failed conversion yielded null.
Related errors
- throw new ArgumentNullException(nameof(iteratorMethod))
- throw new ArgumentNullException(nameof(scheduler))
- throw new ArgumentNullException(nameof(source))
- Expected Qbservable.ToQueryable.
- expression
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/9835a24db91ea93f.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/QbservableEx.Homoicon.cs:1025
#endif
#if !STABLE
/// <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>
[Experimental]
public static IQbservable<TSource> Expand<TSource>(this IQbservable<TSource> source, Expression<Func<TSource, IObservable<TSource>>> selector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (selector == null)
throw new ArgumentNullException(nameof(selector));
return source.Provider.CreateQuery<TSource>(
Expression.Call(
null,
new Func<IQbservable<TSource>, Expression<Func<TSource, IObservable<TSource>>>, IQbservable<TSource>>(Expand<TSource>).Method,
source.Expression,
selector
)
);
}
#endif
#if !STABLE
/// <summary>
/// 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>View on GitHub (pinned to 94b5d5ab91)