dotnet/reactive · error · ArgumentNullException
source
Error message
source
What it means
The Delay operator throws ArgumentNullException because the required source observable was null. System.Reactive.Async operators eagerly validate arguments at the point of composition rather than deferring failure to subscription, so callers get an immediate, precise stack trace. Any extension-method call with a null first argument is rejected before an operator pipeline is built.
Solutions
- Ensure the source observable is initialized before calling Delay; never let a producer return a null IAsyncObservable.
- Add an explicit null check or throw a meaningful exception at the call site to surface where the null came from.
- If the source may legitimately be absent, use AsyncObservable.Empty<TSource>() (or a coalescing expression) instead of passing null.
Example fix
// before var delayed = maybeSource?.Delay(TimeSpan.FromSeconds(1)); // NRE/ANE risk // after var delayed = (maybeSource ?? AsyncObservable.Empty<int>()).Delay(TimeSpan.FromSeconds(1));
Defensive patterns
Strategy: validation
Validate before calling
if (source is null) throw new InvalidOperationException("source observable not initialized before Delay");
var delayed = source.Delay(TimeSpan.FromSeconds(1)); Type guard
static bool IsUsableSource<TSource>(IAsyncObservable<TSource>? s) => s is not null;
Try / catch
try { var delayed = source.Delay(dueTime); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* supply fallback observable or fail fast with context */ } Prevention
- Never return null from methods typed as IAsyncObservable<T>; return Empty or Throw instead.
- Enable nullable reference types so null sources surface at compile time.
- Coalesce nullable observable fields at pipeline-construction time.
When it happens
Trigger: Calling AsyncObservable.Delay<TSource>(null, dueTime) — i.e. the IAsyncObservable<TSource> 'source' argument is null, for example when a factory method returned null, a nullable field was never assigned, or a conditional chain short-circuited to null.
Common situations: Chaining .Delay(...) off a method that can return null instead of an empty/throwing observable; caching an observable in a nullable field and using it before initialization; refactoring where a source variable became nullable and the compiler warning was ignored.
Related errors
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'error')
- ArgumentNullException
- scheduler
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/d3d591dcbaefc317.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Delay.cs:20
// 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.Collections.Generic;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
// TODO: Add overloads with DateTimeOffset and with duration selector.
public partial class AsyncObservable
{
public static IAsyncObservable<TSource> Delay<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
return Create(
source,
dueTime,
static async (source, dueTime, observer) =>
{
var (sink, drain) = await AsyncObserver.Delay(observer, dueTime).ConfigureAwait(false);
var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
return StableCompositeAsyncDisposable.Create(subscription, drain);
});
}
public static IAsyncObservable<TSource> Delay<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
{
if (source == null)
throw new ArgumentNullException(nameof(source));View on GitHub (pinned to 94b5d5ab91)