dotnet/reactive · error · ArgumentNullException

func

Error message

func

What it means

AsyncObserver.Scan<TSource>(observer, Func<TSource,TSource,TSource>) throws ArgumentNullException (paramName "func") because the accumulator delegate was null. This observer-level factory requires a combining function to maintain the running value across OnNextAsync invocations.

Solutions

  1. Supply the accumulator: AsyncObserver.Scan(observer, (acc, x) => acc + x).
  2. Ensure the delegate is assigned before the observer factory call.
  3. Use the public source.Scan(func) operator so argument wiring is handled centrally.

Example fix

// before
var obs = AsyncObserver.Scan(observer, (Func<int, int, int>)null); // throws

// after
var obs = AsyncObserver.Scan(observer, (acc, x) => acc + x);
Defensive patterns

Strategy: validation

Validate before calling

if (func is null) throw new InvalidOperationException("accumulator required by AsyncObserver.Scan");
var obs = AsyncObserver.Scan(observer, func);

Type guard

static bool IsValidAccumulator<TSource>(Func<TSource, TSource, TSource>? f) => f is not null;

Try / catch

try { var obs = AsyncObserver.Scan(observer, f); }
catch (ArgumentNullException ex) when (ex.ParamName == "func") { throw new OperatorConfigurationException("null accumulator", ex); }

Prevention

When it happens

Trigger: Calling AsyncObserver.Scan(observer, null) — a null Func<TSource,TSource,TSource> forwarded from a custom operator or a null variable that was meant to hold the lambda.

Common situations: Hand-written operators delegating to AsyncObserver.Scan with a delegate resolved too late; tests constructing observers directly; refactoring that split func acquisition from observer creation.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Scan.cs:71

                throw new ArgumentNullException(nameof(source));
            if (func == null)
                throw new ArgumentNullException(nameof(func));

            return CreateAsyncObservable<TResult>.From(
                source,
                (func, seed),
                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.Scan(observer, state.seed, state.func)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> Scan<TSource>(IAsyncObserver<TSource> observer, Func<TSource, TSource, TSource> func)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (func == null)
                throw new ArgumentNullException(nameof(func));

            var hasValue = false;
            var value = default(TSource);

            return Create<TSource>(
                async x =>
                {
                    if (hasValue)
                    {
                        try
                        {
                            value = func(value, x);
                        }
                        catch (Exception ex)
                        {
                            await observer.OnErrorAsync(ex).ConfigureAwait(false);
                            return;
                        }

View on GitHub (pinned to 94b5d5ab91)