dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(source));

Error message

throw new ArgumentNullException(nameof(source));

What it means

The Sample<TSource,TSample>(source, sampler) extension throws ArgumentNullException when the source async observable is null. System.Reactive.Async validates all public arguments eagerly at call time rather than failing later inside the subscription pipeline, so you get a synchronous, precise stack trace instead of a deferred NRE when the operator body runs.

Solutions

  1. Ensure the source observable is created before calling Sample (e.g. AsyncObservable.Interval, FromEvent, etc.) and that no factory returns null
  2. Add a null check at the composition site and throw a descriptive exception or fall back to an empty observable
  3. Use the null-coalescing pattern: (maybeSource ?? AsyncObservable.Empty<TSource>()).Sample(sampler)
  4. Check upstream library/API that should supply the observable for documented null returns

Example fix

// before
IAsyncObservable<Price> prices = GetPriceStream(); // may return null
var sampled = prices.Sample(ticks);
// after
var src = GetPriceStream() ?? AsyncObservable.Empty<Price>();
var sampled = src.Sample(ticks);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new ArgumentNullException(nameof(source));
var sampled = source.Sample(sampler);

Type guard

static bool IsNotNull<T>(T? arg) where T : class => arg is not null;

Try / catch

try
{
    var sampled = source.Sample(sampler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    // log and fall back to an empty stream
    sampled = AsyncObservable.Empty<TSource>();
}

Prevention

When it happens

Trigger: Calling source.Sample(sampler) where the IAsyncObservable<TSource> variable is null — typically because a factory method, dictionary lookup, or conditional composition returned null instead of an observable.

Common situations: A helper method returns null when an event stream is not yet initialized; a memoization cache miss yields null; refactoring moved the observable creation after the Sample call; DI container registered a null binding.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Sample.cs:17

// 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.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;

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

            return CreateAsyncObservable<TSource>.From(
                source,
                sampler,
                static async (source, sampler, observer) =>
                {
                    var (sourceSink, samplerSink) = AsyncObserver.Sample<TSource, TSample>(observer);

                    var sourceSubscription = await source.SubscribeSafeAsync(sourceSink).ConfigureAwait(false);
                    var samplerSubscription = await sampler.SubscribeSafeAsync(samplerSink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(sourceSubscription, samplerSubscription);
                });
        }

        public static IAsyncObservable<TSource> Sample<TSource>(this IAsyncObservable<TSource> source, TimeSpan interval)

View on GitHub (pinned to 94b5d5ab91)