dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'func')

Error message

Value cannot be null. (Parameter 'func')

What it means

System.ArgumentNullException thrown by the sync Aggregate overload of IAsyncObservable<T> when the accumulator delegate 'func' is null. The operator eagerly validates all arguments before creating the subscription pipeline, since a null accumulator would only fail mid-stream otherwise. This fail-fast style is used across all AsyncRx.NET operators.

Solutions

  1. Pass a non-null accumulator lambda, e.g. source.Aggregate((acc, x) => acc + x).
  2. If the delegate comes from a variable, check it for null before calling Aggregate and substitute a default.
  3. Ensure any factory/method-group expression used as 'func' actually returns a delegate instance at runtime.

Example fix

// before
Func<int, int, int> acc = GetAccumulator(); // may return null
var result = source.Aggregate(acc);

// after
var acc = GetAccumulator() ?? ((a, x) => a + x);
var result = source.Aggregate(acc);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new ArgumentNullException(nameof(source));
if (func is null) throw new ArgumentNullException(nameof(func));
var result = source.Aggregate(func);

Type guard

static bool IsValidAggregateArgs<TSource>(IAsyncObservable<TSource>? source, Func<TSource, TSource, TSource>? func)
    => source is not null && func is not null;

Try / catch

try { var result = source.Aggregate(func); }
catch (ArgumentNullException ex) when (ex.ParamName == "func") { /* supply default accumulator */ }

Prevention

When it happens

Trigger: Calling source.Aggregate(null) — i.e. invoking the two-generic-parameter Aggregate extension (Aggregate.cs:16 guard) with a null Func<TSource,TSource,TSource>.

Common situations: Passing a method group that resolves to null (e.g. a nullable static field holding a comparer/accumulator), conditional delegates assigned from configuration that was never initialized, or refactoring that removed the lambda but left the call site.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Aggregate.cs:16

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> Aggregate<TSource>(this IAsyncObservable<TSource> source, Func<TSource, TSource, TSource> func)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (func == null)
                throw new ArgumentNullException(nameof(func));

            return CreateAsyncObservable<TSource>.From(
                source,
                func,
                static (source, func, observer) => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, func)));
        }

        public static IAsyncObservable<TSource> Aggregate<TSource>(this IAsyncObservable<TSource> source, Func<TSource, TSource, ValueTask<TSource>> func)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (func == null)
                throw new ArgumentNullException(nameof(func));

            return CreateAsyncObservable<TSource>.From(
                source,
                func,
                static (source, func, observer) => source.SubscribeSafeAsync(AsyncObserver.Aggregate(observer, func)));

View on GitHub (pinned to 94b5d5ab91)