dotnet/reactive · error · ArgumentNullException

source

Error message

source

What it means

The TimeSpan-based DelaySubscription operator throws ArgumentNullException because the source observable is null. DelaySubscription postpones the Subscribe call itself rather than the notifications; it still requires a real target observable to subscribe to later, so null is rejected at composition time.

Solutions

  1. Initialize the source observable before applying DelaySubscription.
  2. Coalesce null sources to AsyncObservable.Empty<TSource>() when absence is legitimate.
  3. Add a guard or debug assertion at the pipeline construction site to catch nulls early.

Example fix

// before
var sub = maybeSource.DelaySubscription(TimeSpan.FromSeconds(5));
// after
var sub = (maybeSource ?? AsyncObservable.Empty<int>()).DelaySubscription(TimeSpan.FromSeconds(5));
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new InvalidOperationException("DelaySubscription requires a source; got null");
var sub = source.DelaySubscription(TimeSpan.FromSeconds(5));

Type guard

static bool Delayable<TSource>(IAsyncObservable<TSource>? s) => s is not null;

Try / catch

try { var s = source.DelaySubscription(due); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { var s = AsyncObservable.Empty<int>().DelaySubscription(due); }

Prevention

When it happens

Trigger: Calling DelaySubscription<TSource>(null, dueTime) — the overload without an explicit scheduler.

Common situations: Building pipelines from nullable observables obtained from caches or optionals; misordered initialization where DelaySubscription is applied before the source is created.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/DelaySubscription.cs:15

// 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;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return DelaySubscription(source, dueTime, TaskPoolAsyncScheduler.Default);
        }

        public static IAsyncObservable<TSource> DelaySubscription<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime, IAsyncScheduler scheduler)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return Create(
                source,
                (dueTime, scheduler),
                static async (source, state, observer) =>
                {
                    var d = new CompositeAsyncDisposable();

View on GitHub (pinned to 94b5d5ab91)