dotnet/reactive · error · ArgumentNullException

sampler

Error message

sampler

What it means

The sampler overload Sample<TSource, TSample>(IObservable<TSource>, IObservable<TSample>) throws ArgumentNullException when the sampler observable is null. The sampler drives emission of the latest source value, so it must be a valid observable.

Solutions

  1. Ensure the sampler observable is created and assigned before the Sample call.
  2. Guard: if sampler == null, decide whether to use the time-based overload Sample(source, interval) instead.
  3. Fix the producer of the sampler so it never returns null (use Observable.Never<TSample>() as a do-nothing sampler).

Example fix

// before
var result = source.Sample(sampler); // sampler is null

// after
var result = source.Sample(sampler ?? Observable.Never<Unit>());
Defensive patterns

Strategy: validation

Validate before calling

if (sampler == null)
    sampler = Observable.Never<TSample>(); // no samples will be emitted
var result = source.Sample(sampler);

Type guard

static bool HasValidSampler<TSource, TSample>(IObservable<TSource> source, IObservable<TSample> sampler) =>
    source != null && sampler != null;

Try / catch

try
{
    var result = source.Sample(sampler);
}
catch (ArgumentNullException)
{
    var result = source.Sample(TimeSpan.FromSeconds(1)); // fall back to time-based sampling
}

Prevention

When it happens

Trigger: Calling source.Sample(null) or Observable.Sample(source, (IObservable<TSample>)null) — a null sampler, often from an unassigned signal stream or a failed lookup of the sampler sequence.

Common situations: A 'trigger' stream field never initialized; an event-to-observable conversion that returned null; mistaking the overload set and passing null where a TimeSpan was expected is a compile error, so this occurs with dynamic/reflective composition or DI.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:915

        /// Samples the source observable sequence using a sampler observable sequence producing sampling ticks.
        /// Upon each sampling tick, the latest element (if any) in the source sequence during the last sampling interval is sent to the resulting sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TSample">The type of the elements in the sampling sequence.</typeparam>
        /// <param name="source">Source sequence to sample.</param>
        /// <param name="sampler">Sampling tick sequence.</param>
        /// <returns>Sampled observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="sampler"/> is null.</exception>
        public static IObservable<TSource> Sample<TSource, TSample>(this IObservable<TSource> source, IObservable<TSample> sampler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (sampler == null)
            {
                throw new ArgumentNullException(nameof(sampler));
            }

            return s_impl.Sample(source, sampler);
        }

        #endregion

        #region + Skip +

        /// <summary>
        /// Skips elements for the specified duration from the start of the observable source sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence to skip elements for.</param>
        /// <param name="duration">Duration for skipping elements from the start of the sequence.</param>
        /// <returns>An observable sequence with the elements skipped during the specified duration from the start of the source sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="duration"/> is less than TimeSpan.Zero.</exception>

View on GitHub (pinned to 94b5d5ab91)