dotnet/reactive · error · ArgumentNullException
throw new…
Error message
throw new ArgumentNullException(nameof(timeoutDurationSelector));
What it means
The Timeout(source, timeoutDurationSelector) overload throws ArgumentNullException because the timeoutDurationSelector delegate is null. This selector computes a per-item timeout stream, so it is mandatory for the operator. The check runs eagerly when the query is composed.
Solutions
- Pass a real selector, e.g. item => Observable.Timer(TimeSpan.FromSeconds(1))
- If the selector is optional, provide a default like _ => Observable.Never<TTimeout>()
- Guard the delegate for null before composing the query
Example fix
// before source.Timeout(_timeoutSelector) // after var selector = _timeoutSelector ?? (_ => Observable.Timer(TimeSpan.FromSeconds(10))); source.Timeout(selector)
Defensive patterns
Strategy: validation
Validate before calling
if (timeoutDurationSelector is null)
throw new InvalidOperationException("timeoutDurationSelector must be provided.");
// or default it:
var selector = timeoutDurationSelector ?? (_ => Observable.Never<TTimeout>()); Type guard
static bool IsValidSelector<TSource, TTimeout>(Func<TSource, IObservable<TTimeout>> f) => f is not null;
Try / catch
try
{
result = source.Timeout(selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "timeoutDurationSelector")
{
result = source.Timeout(_ => Observable.Never<TTimeout>());
} Prevention
- Do not give optional Func parameters a default of null; require them or default to Observable.Never<T>()
- Wire strategy/policy delegates in the constructor so they cannot be unset
- Validate delegates at the boundary where configuration is loaded
When it happens
Trigger: Calling source.Timeout(selector) with a null Func<TSource, IObservable<TTimeout>, e.g. an optional selector parameter left at its default of null.
Common situations: Optional method parameters of type Func<T,...> defaulting to null and passed straight through; a strategy object whose selector delegate was never assigned; reflection-based invocation with missing configuration.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- throw new ArgumentNullException(nameof(firstTimeout));
- throw new ArgumentNullException(nameof(other));
- Argument cannot be null (Parameter name: actionAsync)
- condition
- defaultSource
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/b19d33e1ff0217bf.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:1904
/// Applies a timeout policy to the observable sequence based on a timeout duration computed for each element.
/// 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="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="timeoutDurationSelector"/> is null.</exception>
public static IObservable<TSource> Timeout<TSource, TTimeout>(this IObservable<TSource> source, Func<TSource, IObservable<TTimeout>> timeoutDurationSelector)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (timeoutDurationSelector == null)
{
throw new ArgumentNullException(nameof(timeoutDurationSelector));
}
return s_impl.Timeout(source, timeoutDurationSelector);
}
/// <summary>
/// Applies a timeout policy to the observable sequence based on a timeout duration computed for each 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="timeoutDurationSelector">Selector to retrieve an observable sequence that represents the timeout between the current element and the next element.</param>
/// <param name="other">Sequence to return in case of a timeout.</param>
/// <returns>The source sequence switching to the other sequence in case of a timeout.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="timeoutDurationSelector"/> or <paramref name="other"/> is null.</exception>
public static IObservable<TSource> Timeout<TSource, TTimeout>(this IObservable<TSource> source, Func<TSource, IObservable<TTimeout>> timeoutDurationSelector, IObservable<TSource> other)
{View on GitHub (pinned to 94b5d5ab91)