dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(sampler));

Error message

throw new ArgumentNullException(nameof(sampler));

What it means

The Sample<TSource,TSample>(source, sampler) overload throws ArgumentNullException when the sampler observable is null. The sampler is the stream whose emissions trigger publishing the latest source value, so the operator requires both streams up front and validates them synchronously.

Solutions

  1. Create the sampler before calling Sample (e.g. AsyncObservable.Interval(period) or another hot stream)
  2. Guard at the composition site: if sampler == null, substitute AsyncObservable.Interval(defaultPeriod) or Empty
  3. Fix the factory/DI path that produced the null sampler
  4. Wrap in a helper that validates both arguments and throws a domain-specific error

Example fix

// before
var sampled = prices.Sample(configuredSampler); // null when config missing
// after
var sampler = configuredSampler ?? AsyncObservable.Interval(TimeSpan.FromSeconds(1));
var sampled = prices.Sample(sampler);
Defensive patterns

Strategy: validation

Validate before calling

if (sampler is null) sampler = AsyncObservable.Interval(TimeSpan.FromSeconds(1));
var sampled = source.Sample(sampler);

Type guard

static bool HasSampler<TSample>(IAsyncObservable<TSample>? s) => s is not null;

Try / catch

try
{
    var sampled = source.Sample(sampler);
}
catch (ArgumentNullException ex) when (ex.ParamName == "sampler")
{
    sampler = AsyncObservable.Interval(defaultPeriod);
    sampled = source.Sample(sampler);
}

Prevention

When it happens

Trigger: Calling source.Sample(sampler) with a null sampler — e.g. a timer/sampler stream that failed to initialize, a conditional that returns null instead of a default sampler, or passing the result of a lookup that missed.

Common situations: Sampler built from a configuration-driven interval where config was missing and the builder returned null; unit test forgot to set up the sampler; a NuGet/version change made a previously non-null sampler nullable.

Related errors


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

Appendix: source

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

// 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)
        {
            if (source == null)

View on GitHub (pinned to 94b5d5ab91)