dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'merge')

Error message

Value cannot be null. (Parameter 'merge')

What it means

System.ArgumentNullException thrown by Observable.Collect(source, newCollector, merge) when the merge aggregation delegate is null. Rx validates arguments in order, so this only occurs when both source and newCollector are valid but the combining function is missing.

Solutions

  1. Provide a non-null merge Func<TResult, TSource, TResult>, e.g. (acc, x) => acc + x.
  2. Reorder arguments if the merge lambda was accidentally placed in the wrong position.
  3. Guard nullable delegate fields before the call.

Example fix

// before
var result = source.Collect(() => 0, mergeFn); // mergeFn == null
// after
var result = source.Collect(() => 0, (acc, x) => acc + x);
Defensive patterns

Strategy: validation

Validate before calling

if (merge is null) throw new InvalidOperationException("Collect requires a non-null merge function");

Try / catch

try
{
    var result = source.Collect(() => seed, merge);
}
catch (ArgumentNullException ex) when (ex.ParamName == "merge")
{
    // supply or repair the aggregation function
}

Prevention

When it happens

Trigger: Calling Collect(source, () => seed, null) — usually a misordered argument list, a null Func field, or a conditional that produced no combiner.

Common situations: Refactoring that dropped the merge lambda; passing a method group on a null object; generic wrappers that forward a possibly-null delegate.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Blocking.cs:59

        /// <param name="newCollector">Factory to create a new collector object.</param>
        /// <param name="merge">Merges a sequence element with the current collector.</param>
        /// <returns>The enumerable sequence that returns collected/aggregated elements from the source sequence upon each iteration.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="newCollector"/> or <paramref name="merge"/> is null.</exception>
        public static IEnumerable<TResult> Collect<TSource, TResult>(this IObservable<TSource> source, Func<TResult> newCollector, Func<TResult, TSource, TResult> merge)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

            return s_impl.Collect(source, newCollector, merge);
        }

        /// <summary>
        /// Produces an enumerable sequence that returns elements collected/aggregated from the source sequence between consecutive iterations.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TResult">The type of the elements produced by the merge operation during collection.</typeparam>
        /// <param name="source">Source observable sequence.</param>
        /// <param name="getInitialCollector">Factory to create the initial collector object.</param>
        /// <param name="merge">Merges a sequence element with the current collector.</param>
        /// <param name="getNewCollector">Factory to replace the current collector by a new collector.</param>
        /// <returns>The enumerable sequence that returns collected/aggregated elements from the source sequence upon each iteration.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="getInitialCollector"/> or <paramref name="merge"/> or <paramref name="getNewCollector"/> is null.</exception>
        public static IEnumerable<TResult> Collect<TSource, TResult>(this IObservable<TSource> source, Func<TResult> getInitialCollector, Func<TResult, TSource, TResult> merge, Func<TResult, TResult> getNewCollector)
        {

View on GitHub (pinned to 94b5d5ab91)