dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'getNewCollector')

Error message

Value cannot be null. (Parameter 'getNewCollector')

What it means

System.ArgumentNullException thrown by the 4-argument Observable.Collect overload when getNewCollector is null. This delegate re-arms the collector after each emitted value; it is the last argument validated.

Solutions

  1. Supply a valid Func<TResult, TResult> renewal delegate, e.g. acc => acc (identity) if no reset is needed.
  2. If no renewal behavior is required, use the 3-argument Collect overload instead of passing null.
  3. Audit wrapper methods that forward optional delegates.

Example fix

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

Strategy: validation

Validate before calling

if (getNewCollector is null) throw new InvalidOperationException("Collect requires a non-null renewal function");
// if no reset is needed, pass the identity function:
var renew = getNewCollector ?? (acc => acc);

Try / catch

try
{
    var result = source.Collect(seed, merge, getNewCollector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "getNewCollector")
{
    // switch to the 3-arg Collect overload or supply identity renewal
}

Prevention

When it happens

Trigger: Calling Collect(source, seed, merge, null) — often because the caller thought the 4th argument was optional or copied the 3-arg call shape and appended null.

Common situations: Porting code from the 3-argument Collect overload; wrappers that only sometimes supply a renewal function; reflection-based invocation with a missing argument.

Related errors


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

Appendix: source

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

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

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

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

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

            return s_impl.Collect(source, getInitialCollector, merge, getNewCollector);
        }

        #endregion

        #region + First +

        /// <summary>
        /// Returns the first element of an observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source observable sequence.</param>
        /// <returns>The first element in the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>
        /// <seealso cref="Observable.FirstAsync{TSource}(IObservable{TSource})"/>

View on GitHub (pinned to 94b5d5ab91)