dotnet/reactive · error · ArgumentNullException
ArgumentNullException
Error message
ArgumentNullException
What it means
The Timeout operator shifts to an error/completion if the source produces no notification within dueTime, and it requires a non-null source observable. If source is null the operator cannot subscribe, so it throws ArgumentNullException at composition time, before any timer is scheduled.
Solutions
- Ensure the source observable is non-null before applying Timeout
- Guard with a null check or substitute AsyncObservable.Never<TSource>()/Empty<TSource>() for a null source
- Trace the upstream composition to find where null originated
Example fix
// before var withTimeout = source.Timeout(TimeSpan.FromSeconds(5)); // source null // after var withTimeout = (source ?? AsyncObservable.Never<int>()).Timeout(TimeSpan.FromSeconds(5));
Defensive patterns
Strategy: validation
Validate before calling
if (source is null) throw new InvalidOperationException("source observable not initialized");
var withTimeout = source.Timeout(TimeSpan.FromSeconds(5)); Type guard
bool IsSubscribable<TSource>(IAsyncObservable<TSource>? s) => s is not null;
Try / catch
try
{
withTimeout = source.Timeout(TimeSpan.FromSeconds(5));
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
withTimeout = AsyncObservable.Never<int>(); // or surface configuration error
} Prevention
- Check the pipeline producing source before applying Timeout
- Use Never/Empty sentinels instead of null observables
- Enable nullable reference types so null sources surface at compile time
When it happens
Trigger: Calling source.Timeout(dueTime) where source == null — e.g. a null returned by an upstream factory, failed DI resolution, or a nullable variable not checked before chaining.
Common situations: Long operator chains where an early operator returned null; conditional pipeline construction missing an assignment; tests that forget to instantiate the observable under timeout behavior.
Related errors
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/d535238578c7516c.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Timeout.cs:17
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> Timeout<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return CreateAsyncObservable<TSource>.From(
source,
dueTime,
static async (source, dueTime, observer) =>
{
var sourceSubscription = new SingleAssignmentAsyncDisposable();
var (sink, disposable) = await AsyncObserver.Timeout(observer, sourceSubscription, dueTime).ConfigureAwait(false);
var sourceSubscriptionInner = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
await sourceSubscription.AssignAsync(sourceSubscriptionInner).ConfigureAwait(false);
return disposable;
});
}
View on GitHub (pinned to 94b5d5ab91)