dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(sources))

Error message

throw new ArgumentNullException(nameof(sources))

What it means

ForkJoin(params IObservable<TSource>[]) throws ArgumentNullException when the sources array itself is null (as opposed to empty, which is allowed). The guard exists before building the MethodCallExpression so the expression tree has a valid arguments array.

Solutions

  1. Pass at least one non-null observable or an empty array instead of null
  2. Check the array for null before calling ForkJoin
  3. Ensure the upstream list used to build the array is non-null

Example fix

// before
provider.ForkJoin((IObservable<int>[])null);
// after
provider.ForkJoin(new IObservable<int>[] { src1, src2 });
Defensive patterns

Strategy: validation

Validate before calling

if (sources is null) throw new ArgumentNullException(nameof(sources));

Type guard

bool IsValidSources(IObservable<T>[] s) => s is not null;

Try / catch

try { var q = provider.ForkJoin(sources); } catch (ArgumentNullException ex) when (ex.ParamName == "sources") { /* handle null sources */ }

Prevention

When it happens

Trigger: Calling provider.ForkJoin(null) where the null literal or null array variable is passed for the params sources parameter.

Common situations: Passing a null IObservable<TSource>[] variable, or forwarding a null collection converted with .ToArray() from a null source list.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/QbservableEx.Homoicon.cs:1087

#endif

#if !STABLE
        /// <summary>
        /// Runs all specified observable sequences in parallel and collects their last elements.
        /// </summary>
        /// <param name="provider">Query provider used to construct the <see cref="IQbservable{T}"/> data source.</param>
        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
        /// <param name="sources">Observable sequence to collect the last elements for.</param>
        /// <returns>An observable sequence with an array collecting the last elements of all the input sequences.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="sources" /> is null.</exception>
        [Experimental]
        public static IQbservable<TSource[]> ForkJoin<TSource>(this IQbservableProvider provider, params IObservable<TSource>[] sources)
        {
            if (provider == null)
                throw new ArgumentNullException(nameof(provider));
            if (sources == null)
                throw new ArgumentNullException(nameof(sources));

            return provider.CreateQuery<TSource[]>(
                Expression.Call(
                    null,
                    new Func<IQbservableProvider, IObservable<TSource>[], IQbservable<TSource[]>>(ForkJoin<TSource>).Method,
                    Expression.Constant(provider, typeof(IQbservableProvider)),
                    GetSourceExpression(sources)
                )
            );
        }
#endif

#if !STABLE
        /// <summary>
        /// Runs all observable sequences in the enumerable sources sequence in parallel and collect their last elements.
        /// </summary>
        /// <param name="provider">Query provider used to construct the <see cref="IQbservable{T}"/> data source.</param>
        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>

View on GitHub (pinned to 94b5d5ab91)