dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

The async-selector overload Sum(source, Func<TSource, ValueTask<int>>) validates the source first and throws ArgumentNullException with message "Value cannot be null. (Parameter 'source')" when the observable is null. The operator needs a live sequence to subscribe to.

Solutions

  1. Ensure the observable is non-null before calling Sum; check the producing method's failure paths.
  2. Substitute AsyncObservable.Empty<int>() (or appropriate type) as a fallback.
  3. Fix the upstream factory/operator that returns null.

Example fix

// before
var total = await GetOrders().Sum(o => GetQtyAsync(o)); // GetOrders() returned null
// after
var src = GetOrders() ?? AsyncObservable.Empty<Order>();
var total = await src.Sum(o => GetQtyAsync(o));
Defensive patterns

Strategy: validation

Validate before calling

if (source == null)
    source = AsyncObservable.Empty<TSource>();

Type guard

static bool IsObservable<T>(IAsyncObservable<T>? o) => o is not null;

Try / catch

try
{
    var total = await source.Sum(asyncSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    logger.LogError(ex, "Null source passed to Sum");
    total = 0;
}

Prevention

When it happens

Trigger: Invoking the extension on a null receiver (e.g. source-producing factory returned null) or explicitly passing null as the first argument.

Common situations: An upstream method that returns IAsyncObservable<T> failing and returning null; optional sequence resolution in configuration; test scaffolding passing null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Sum.Generated.cs:35

        }

        public static IAsyncObservable<Int32> Sum<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int32> selector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));

            return CreateAsyncObservable<Int32>.From(
                source,
                selector,
                static (source, selector, observer) => source.SubscribeSafeAsync(AsyncObserver.SumInt32(observer, selector)));
        }

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

            return CreateAsyncObservable<Int32>.From(
                source,
                selector,
                static (source, selector, observer) => source.SubscribeSafeAsync(AsyncObserver.SumInt32(observer, selector)));
        }

        public static IAsyncObservable<Int32?> Sum(this IAsyncObservable<Int32?> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return Create(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.SumNullableInt32(observer)));
        }

        public static IAsyncObservable<Int32?> Sum<TSource>(this IAsyncObservable<TSource> source, Func<TSource, Int32?> selector)

View on GitHub (pinned to 94b5d5ab91)