dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'collectionSelector')

Error message

Value cannot be null. (Parameter 'collectionSelector')

What it means

In this SelectMany overload the collectionSelector (Func<TSource, IObservable<TCollection>>) determines the inner sequence for each element; it must not be null. The method validates all three arguments eagerly and throws ArgumentNullException naming 'collectionSelector' when it is null.

Solutions

  1. Provide a real collection selector: source.SelectMany(x => x.Children.ToObservable(), (x, c) => ...).
  2. Guard dynamic delegates: if (collectionSelector == null) collectionSelector = x => Observable.Empty<TCollection>();
  3. Confirm the argument order — collectionSelector comes before resultSelector; a swapped/null argument can trigger this.

Example fix

// before
Func<Order, IObservable<Item>> items = null;
var q = orders.SelectMany(items, (o, i) => i.Price);

// after
var q = orders.SelectMany(o => o.Items.ToObservable(), (o, i) => i.Price);
Defensive patterns

Strategy: validation

Validate before calling

if (collectionSelector is null)
    collectionSelector = static _ => Observable.Empty<TCollection>();

Type guard

static bool HasCollSelector<TSrc, TColl>(Func<TSrc, IObservable<TColl>> sel) => sel is not null;

Try / catch

try
{
    var q = source.SelectMany(collectionSelector, resultSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "collectionSelector")
{
    throw new InvalidOperationException("Collection selector missing in SelectMany composition", ex);
}

Prevention

When it happens

Trigger: source.SelectMany(null, (x, c) => result) or passing a null delegate variable into the collectionSelector slot while resultSelector is valid. Thrown at Observable.StandardSequenceOperators.cs:1190.

Common situations: Query-builder patterns where the collection selector is composed conditionally and ends up null; DI/config-injected projection functions that failed to resolve; refactors renaming a method but leaving a null delegate reference.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/2ed70dbfa24249d8. Report an issue: GitHub.

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.StandardSequenceOperators.cs:1190

        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TCollection">The type of the elements in the projected intermediate sequences.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate sequence elements.</typeparam>
        /// <param name="source">An observable sequence of elements to project.</param>
        /// <param name="collectionSelector">A transform function to apply to each element.</param>
        /// <param name="resultSelector">A transform function to apply to each element of the intermediate sequence.</param>
        /// <returns>An observable sequence whose elements are the result of invoking the one-to-many transform function collectionSelector on each element of the input sequence and then mapping each of those sequence elements and their corresponding source element to a result element.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="collectionSelector"/> or <paramref name="resultSelector"/> is null.</exception>
        public static IObservable<TResult> SelectMany<TSource, TCollection, TResult>(this IObservable<TSource> source, Func<TSource, IObservable<TCollection>> collectionSelector, Func<TSource, TCollection, TResult> resultSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (collectionSelector == null)
            {
                throw new ArgumentNullException(nameof(collectionSelector));
            }

            if (resultSelector == null)
            {
                throw new ArgumentNullException(nameof(resultSelector));
            }

            return s_impl.SelectMany(source, collectionSelector, resultSelector);
        }

        /// <summary>
        /// Projects each element of an observable sequence to an observable sequence by incorporating the element's index, invokes the result selector for the source element and each of the corresponding inner sequence's elements, and merges the results into one observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TCollection">The type of the elements in the projected intermediate sequences.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence, obtained by using the selector to combine source sequence elements with their corresponding intermediate sequence elements.</typeparam>
        /// <param name="source">An observable sequence of elements to project.</param>
        /// <param name="collectionSelector">A transform function to apply to each element; the second parameter of the function represents the index of the source element.</param>

View on GitHub (pinned to 94b5d5ab91)