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
- Pass a non-null accumulator lambda, e.g. (acc, x) => acc + x.
- If the accumulator is resolved dynamically, fall back to a no-op reducer when the lookup returns null.
- Enable nullable reference types so a possibly-null Func is caught at compile time.
- 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
- Never store reducer delegates in nullable fields that can default to null; initialize with an identity/no-op function.
- When resolving delegates from registries, always provide a fallback (?? defaultReducer).
- Enable nullable reference types so nullable Func parameters are flagged by the compiler.
- Keep lambdas inline at the call site unless dynamic selection is truly required.
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
- Value cannot be null. (Parameter 'resultSelector')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
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)