dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'clock')

Error message

Value cannot be null. (Parameter 'clock')

What it means

AsyncObserver.Timestamp(observer, clock) throws ArgumentNullException with message "Value cannot be null. (Parameter 'clock')" when the IClock parameter is null. Each element is stamped with clock.Now, so a null clock would break every notification; the library validates it up front.

Solutions

  1. Use the single-argument overload AsyncObserver.Timestamp(observer), which defaults to Clock.Default.
  2. Pass a concrete IClock such as Clock.Default or the test clock instance.
  3. Fix DI/configuration so IClock resolves to a real instance before operator composition.

Example fix

// before
var stamped = AsyncObserver.Timestamp<int>(observer, testClock); // testClock not initialized (null)

// after
testClock ??= new TestClock();
var stamped = AsyncObserver.Timestamp<int>(observer, testClock);
Defensive patterns

Strategy: validation

Validate before calling

if (clock is null)
    throw new InvalidOperationException("IClock must be provided; use Clock.Default or a test clock.");

Type guard

bool HasClock(IClock? clock) => clock is not null;

Try / catch

try
{
    return AsyncObserver.Timestamp(observer, clock);
}
catch (ArgumentNullException ex) when (ex.ParamName == "clock")
{
    return AsyncObserver.Timestamp(observer); // default clock
}

Prevention

When it happens

Trigger: Calling AsyncObserver.Timestamp<T>(observer, clock) with clock == null, e.g. an injected test clock that was never registered, or passing null expecting default-clock behavior.

Common situations: Simulated-time unit tests where the VirtualTimeClock/TestClock registration is missing; refactor to inject IClock left a null field; passing null intentionally in integration glue code.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Timestamp.cs:48

        }
    }

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

            return Timestamp(observer, Clock.Default);
        }

        public static IAsyncObserver<TSource> Timestamp<TSource>(IAsyncObserver<Timestamped<TSource>> observer, IClock clock)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (clock == null)
                throw new ArgumentNullException(nameof(clock));

            return Select<TSource, Timestamped<TSource>>(observer, x => new Timestamped<TSource>(x, clock.Now));
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)