dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(firstTimeout));

Error message

throw new ArgumentNullException(nameof(firstTimeout));

What it means

The Timeout(source, firstTimeout, timeoutDurationSelector) overload throws ArgumentNullException because the firstTimeout sequence is null. firstTimeout defines the timeout window for the very first element and is a required stream. Validation happens eagerly before the query is returned.

Solutions

  1. Pass a real first-timeout stream, e.g. Observable.Timer(TimeSpan.FromSeconds(5))
  2. If there is no initial timeout, use the (source, selector) overload instead
  3. Null-check firstTimeout before composing the query

Example fix

// before
source.Timeout(firstTimeout, selector)
// after
var ft = firstTimeout ?? Observable.Timer(TimeSpan.FromSeconds(5));
source.Timeout(ft, selector)
Defensive patterns

Strategy: validation

Validate before calling

var ft = firstTimeout ?? Observable.Timer(TimeSpan.FromSeconds(5));
var result = source.Timeout(ft, timeoutDurationSelector);

Type guard

static bool IsNonNullStream<T>(IObservable<T> s) => s is not null;

Try / catch

try
{
    result = source.Timeout(firstTimeout, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "firstTimeout")
{
    result = source.Timeout(selector); // no initial timeout window
}

Prevention

When it happens

Trigger: Calling source.Timeout(firstTimeout, selector) with a null IObservable<TTimeout> first-timeout stream.

Common situations: A lazily created warm-up timeout stream that was never assigned; a merged stream expression evaluating to null; config that gates creation of the first-timeout stream.

Understand the failure class

Related errors


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

Appendix: source

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

        /// If the next element isn't received within the computed duration starting from its predecessor, a TimeoutException is propagated to the observer.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <typeparam name="TTimeout">The type of the elements in the timeout sequences used to indicate the timeout duration for each element in the source sequence.</typeparam>
        /// <param name="source">Source sequence to perform a timeout for.</param>
        /// <param name="firstTimeout">Observable sequence that represents the timeout for the first element.</param>
        /// <param name="timeoutDurationSelector">Selector to retrieve an observable sequence that represents the timeout between the current element and the next element.</param>
        /// <returns>The source sequence with a TimeoutException in case of a timeout.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="firstTimeout"/> or <paramref name="timeoutDurationSelector"/> is null.</exception>
        public static IObservable<TSource> Timeout<TSource, TTimeout>(this IObservable<TSource> source, IObservable<TTimeout> firstTimeout, Func<TSource, IObservable<TTimeout>> timeoutDurationSelector)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

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

            return s_impl.Timeout(source, firstTimeout, timeoutDurationSelector);
        }

        /// <summary>
        /// Applies a timeout policy to the observable sequence based on an initial timeout duration for the first element, and a timeout duration computed for each subsequent element.
        /// If the next element isn't received within the computed duration starting from its predecessor, the other observable sequence is used to produce future messages from that point on.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence and the other sequence used upon a timeout.</typeparam>
        /// <typeparam name="TTimeout">The type of the elements in the timeout sequences used to indicate the timeout duration for each element in the source sequence.</typeparam>
        /// <param name="source">Source sequence to perform a timeout for.</param>
        /// <param name="firstTimeout">Observable sequence that represents the timeout for the first element.</param>

View on GitHub (pinned to 94b5d5ab91)