dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(subscriptionDelay));

Error message

throw new ArgumentNullException(nameof(subscriptionDelay));

What it means

In Delay<TSource,TDelay>(source, subscriptionDelay, delayDurationSelector), the subscriptionDelay observable (which delays the initial subscription) is mandatory and must be non-null; the library throws ArgumentNullException when it is null.

Solutions

  1. Pass a real subscription delay, e.g. Observable.Timer(TimeSpan.FromSeconds(1)); use Observable.Timer(TimeSpan.Zero) or Observable.Return(0L) for no subscription delay.
  2. If no subscription delay is needed, switch to the Delay(source, delayDurationSelector) overload.
  3. Fix the producer of subscriptionDelay so it never returns null.
  4. Guard the parameter before the call and throw a descriptive exception or supply a default.

Example fix

// before
var delayed = source.Delay(subscriptionDelay, selector); // subscriptionDelay == null
// after
var delayed = source.Delay(Observable.Timer(TimeSpan.Zero), selector);
Defensive patterns

Strategy: validation

Validate before calling

if (subscriptionDelay is null) subscriptionDelay = Observable.Timer(TimeSpan.Zero);
var delayed = source.Delay(subscriptionDelay, selector);

Type guard

static bool IsNonNullObservable<T>(IObservable<T>? o) => o is not null;

Try / catch

try { var delayed = source.Delay(subscriptionDelay, selector); }
catch (ArgumentNullException ex) when (ex.ParamName == "subscriptionDelay") { /* pass Observable.Timer(TimeSpan.Zero) */ }

Prevention

When it happens

Trigger: Calling the 3-argument overload with null as the subscriptionDelay parameter, e.g. forgetting to supply an Observable.Timer for the subscription delay or a nullable field that was never assigned.

Common situations: Refactoring from the 2-argument selector overload to the 3-argument overload and not understanding subscriptionDelay is required; passing null to 'skip' the subscription delay; DI-provided observables that resolved to null.

Related errors


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

Appendix: source

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

        /// 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)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

            return s_impl.Delay(source, subscriptionDelay, delayDurationSelector);
        }

        #endregion

        #endregion

        #region + DelaySubscription +

        /// <summary>
        /// Time shifts the observable sequence by delaying the subscription with the specified relative time duration.

View on GitHub (pinned to 94b5d5ab91)