dotnet/reactive · error · ArgumentNullException

throw new ArgumentNullException(nameof(clock));

Error message

throw new ArgumentNullException(nameof(clock));

What it means

The clock-taking TimeInterval overload requires a non-null IClock because it reads clock.Now to compute inter-notification intervals. A null clock makes interval computation impossible, so the operator throws ArgumentNullException before building the composed observable.

Solutions

  1. Pass Clock.Default or a TestClock/MockClock instance explicitly
  2. Use the parameterless source.TimeInterval() overload which defaults to Clock.Default
  3. Fix the null-producing clock factory/lookup

Example fix

// before
var intervals = source.TimeInterval(clock); // clock null
// after
var intervals = source.TimeInterval(clock ?? Clock.Default);
Defensive patterns

Strategy: validation

Validate before calling

clock ??= Clock.Default;
var intervals = source.TimeInterval(clock);

Type guard

bool IsValidClock(IClock? c) => c is not null;

Try / catch

try
{
    intervals = source.TimeInterval(clock);
}
catch (ArgumentNullException ex) when (ex.ParamName == "clock")
{
    intervals = source.TimeInterval(); // defaults to Clock.Default
}

Prevention

When it happens

Trigger: Calling source.TimeInterval(clock) with clock == null, e.g. an IClock resolved from config/DI that was never registered or a variable that shadows a null.

Common situations: Missing clock registration in a DI container; test setups where a mock clock was not assigned; forgetting that the parameterless overload defaults to Clock.Default.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/TimeInterval.cs:24

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

            return Create<TSource, TimeInterval<TSource>>(source, static (source, observer) => source.SubscribeSafeAsync(AsyncObserver.TimeInterval(observer)));
        }

        public static IAsyncObservable<TimeInterval<TSource>> TimeInterval<TSource>(this IAsyncObservable<TSource> source, IClock clock)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (clock == null)
                throw new ArgumentNullException(nameof(clock));

            return CreateAsyncObservable<TimeInterval<TSource>>.From(
                source,
                clock,
                static (source, clock, observer) => source.SubscribeSafeAsync(AsyncObserver.TimeInterval(observer, clock))); ;
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> TimeInterval<TSource>(IAsyncObserver<TimeInterval<TSource>> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return TimeInterval(observer, Clock.Default);
        }

View on GitHub (pinned to 94b5d5ab91)