dotnet/reactive · error · ArgumentNullException

throw new…

Error message

throw new ArgumentNullException(nameof(delayDurationSelector));

What it means

Delay<TSource,TDelay>(source, delayDurationSelector) requires a non-null selector function that maps each element to a duration observable. A null selector makes the operator unable to compute any delays, so it throws ArgumentNullException eagerly.

Solutions

  1. Pass a concrete selector lambda, e.g. x => Observable.Timer(TimeSpan.FromMilliseconds(x.Delay)).
  2. Fix the injection/assignment so the selector Func is populated before use.
  3. If the delay should be constant, use the Delay(source, TimeSpan) overload instead of a selector.
  4. Guard: if (selector == null) throw new InvalidOperationException(...) with context, or provide a default selector.

Example fix

// before
Func<Order, IObservable<long>> sel = _config.Selector; // null
var delayed = orders.Delay(sel);
// after
var delayed = orders.Delay(o => Observable.Timer(TimeSpan.FromMilliseconds(o.DelayMs)));
Defensive patterns

Strategy: validation

Validate before calling

if (selector is null) selector = x => Observable.Timer(TimeSpan.FromMilliseconds(x.DelayMs));
var delayed = source.Delay(selector);

Type guard

static bool HasSelector<TSrc,TDur>(Func<TSrc, IObservable<TDur>>? f) => f is not null;

Try / catch

try { var delayed = source.Delay(selector); }
catch (ArgumentNullException ex) when (ex.ParamName == "delayDurationSelector") { /* supply a default selector */ }

Prevention

When it happens

Trigger: Calling Observable.Delay(source, null), or passing a selector variable that is null (a Func field never assigned, a lambda conditional that resolved to null, a strategy object returning a null Func).

Common situations: Configurable pipelines where the selector is injected and the injection failed; reflection-based code passing null delegates; forgetting the lambda when converting from the timespan-based Delay overload.

Related errors


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

Appendix: source

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

        /// <summary>
        /// Time shifts the observable sequence based on a delay selector function for each element.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TDelay">The type of the elements in the delay sequences used to denote the delay duration of each element in the source sequence.</typeparam>
        /// <param name="source">Source sequence to delay values for.</param>
        /// <param name="delayDurationSelector">Selector function to retrieve a sequence indicating the delay for each given element.</param>
        /// <returns>Time-shifted sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="delayDurationSelector"/> is null.</exception>
        public static IObservable<TSource> Delay<TSource, TDelay>(this IObservable<TSource> source, Func<TSource, IObservable<TDelay>> delayDurationSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            return s_impl.Delay(source, delayDurationSelector);
        }

        /// <summary>
        /// Time shifts the observable sequence based on a subscription delay and a delay selector function for each element.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TDelay">The type of the elements in the delay sequences used to denote the delay duration of each element in the source sequence.</typeparam>
        /// <param name="source">Source sequence to delay values for.</param>
        /// <param name="subscriptionDelay">Sequence indicating the delay for the subscription to the source.</param>
        /// <param name="delayDurationSelector">Selector function to retrieve a sequence indicating the delay for each given element.</param>
        /// <returns>Time-shifted sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="subscriptionDelay"/> or <paramref name="delayDurationSelector"/> is null.</exception>
        public static IObservable<TSource> Delay<TSource, TDelay>(this IObservable<TSource> source, IObservable<TDelay> subscriptionDelay, Func<TSource, IObservable<TDelay>> delayDurationSelector)
        {
            if (source == null)

View on GitHub (pinned to 94b5d5ab91)