dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'accumulator')

Error message

Value cannot be null. (Parameter 'accumulator')

What it means

The seeded Aggregate overload throws ArgumentNullException when the accumulator delegate is null. Aggregate requires a Func<TAccumulate, TSource, TAccumulate> to combine the seed with each element; without it the operator is meaningless, so the call fails immediately at the public entry point.

Solutions

  1. Pass a non-null accumulator lambda, e.g. (acc, x) => acc + x.
  2. If the accumulator is resolved dynamically, fall back to a no-op reducer when the lookup returns null.
  3. Enable nullable reference types so a possibly-null Func is caught at compile time.
  4. Throw or log at the point the delegate is produced so the null never reaches Aggregate.

Example fix

// before
Func<int, int, int> acc = reducers.TryGetValue("sum", out var f) ? f : null;
await src.Aggregate(0, acc); // ArgumentNullException

// after
Func<int, int, int> acc = reducers.TryGetValue("sum", out var f) ? f : ((a, x) => a);
await src.Aggregate(0, acc);
Defensive patterns

Strategy: type-guard

Validate before calling

if (accumulator is null) throw new ArgumentNullException(nameof(accumulator)); // fail before entering Rx

Type guard

static Func<TAcc, T, TAcc> NotNull<TAcc, T>(Func<TAcc, T, TAcc>? f) => f ?? throw new ArgumentNullException(nameof(f));

Try / catch

try { var result = source.Aggregate(seed, accumulator); }
catch (ArgumentNullException ex) when (ex.ParamName == "accumulator") { /* supply fallback reducer or surface config bug */ }

Prevention

When it happens

Trigger: Calling Observable.Aggregate(source, seed, null) — typically when the lambda is built conditionally, supplied as a nullable field/property, or passed through from a caller whose argument was null.

Common situations: Storing reducer functions in configuration or a registry that returned null; overloads where the wrong optional parameter was bound; refactors that removed the lambda but left the call site compiling via a nullable delegate type.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Aggregates.cs:35

        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TAccumulate">The type of the result of the aggregation.</typeparam>
        /// <param name="source">An observable sequence to aggregate over.</param>
        /// <param name="seed">The initial accumulator value.</param>
        /// <param name="accumulator">An accumulator function to be invoked on each element.</param>
        /// <returns>An observable sequence containing a single element with the final accumulator value.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="accumulator"/> is null.</exception>
        /// <remarks>The return type of this operator differs from the corresponding operator on IEnumerable in order to retain asynchronous behavior.</remarks>
        public static IObservable<TAccumulate> Aggregate<TSource, TAccumulate>(this IObservable<TSource> source, TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> accumulator)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            return s_impl.Aggregate(source, seed, accumulator);
        }

        /// <summary>
        /// Applies an accumulator function over an observable sequence, returning the result of the aggregation as a single element in the result sequence. The specified seed value is used as the initial accumulator value,
        /// and the specified result selector function is used to select the result value.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TAccumulate">The type of the accumulator value.</typeparam>
        /// <typeparam name="TResult">The type of the resulting value.</typeparam>
        /// <param name="source">An observable sequence to aggregate over.</param>
        /// <param name="seed">The initial accumulator value.</param>
        /// <param name="accumulator">An accumulator function to be invoked on each element.</param>
        /// <param name="resultSelector">A function to transform the final accumulator value into the result value.</param>
        /// <returns>An observable sequence containing a single element with the final accumulator value.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="accumulator"/> or <paramref name="resultSelector"/> is null.</exception>

View on GitHub (pinned to 94b5d5ab91)