dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'timeSpan')

Error message

Value cannot be null. (Parameter 'timeSpan')

What it means

Buffer<TSource>(source, timeSpan) throws ArgumentNullException(nameof(timeSpan)) when timeSpan < TimeSpan.Zero. A negative buffer window is meaningless (a window cannot have negative duration), so the operator rejects it. Semantically this is an out-of-range value, but the library throws ArgumentNullException with the parameter name 'timeSpan'. The check runs at pipeline-construction time.

Solutions

  1. Ensure the TimeSpan is >= TimeSpan.Zero before calling; clamp: if (ts < TimeSpan.Zero) ts = TimeSpan.Zero; (or a sensible positive default).
  2. Fix the computation producing the negative duration (e.g. clamp end >= start before subtracting).
  3. Validate configured durations at startup and reject negative values with a clear error.

Example fix

// before
var window = end - start; // end < start -> negative
var batches = source.Buffer(window);
// after
var window = end > start ? end - start : TimeSpan.FromSeconds(1);
var batches = source.Buffer(window);
Defensive patterns

Strategy: validation

Validate before calling

if (timeSpan < TimeSpan.Zero) throw new ArgumentException("Buffer window must be non-negative", nameof(timeSpan));

Type guard

bool IsValidWindow(TimeSpan ts) => ts >= TimeSpan.Zero;

Try / catch

try { var batches = source.Buffer(timeSpan); }
catch (ArgumentNullException ex) when (ex.ParamName == "timeSpan") { throw new InvalidOperationException("Buffer window must be >= TimeSpan.Zero; check duration computation", ex); }

Prevention

When it happens

Trigger: Calling source.Buffer(TimeSpan.FromSeconds(-1)) or a TimeSpan computed by subtraction (e.g. end - start where end < start) yielding a negative duration.

Common situations: Window duration derived from clock arithmetic that can go negative near boundaries; config values parsed with a sign error; Duration properties defaulted to -1 as a sentinel and passed through unvalidated.

Related errors


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

Appendix: source

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

            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (count <= 0)
                throw new ArgumentNullException(nameof(count));
            if (skip <= 0)
                throw new ArgumentNullException(nameof(skip));

            return CreateAsyncObservable<IList<TSource>>.From(
                source,
                (count, skip),
                static (source, state, observer) => source.SubscribeSafeAsync(AsyncObserver.Buffer(observer, state.count, state.skip)));
        }

        public static IAsyncObservable<IList<TSource>> Buffer<TSource>(this IAsyncObservable<TSource> source, TimeSpan timeSpan)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (timeSpan < TimeSpan.Zero)
                throw new ArgumentNullException(nameof(timeSpan));

            return CreateAsyncObservable<IList<TSource>>.From(
                source,
                timeSpan,
                static async (source, timeSpan, observer) =>
                {
                    var (sink, timer) = await AsyncObserver.Buffer(observer, timeSpan).ConfigureAwait(false);

                    var subscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(subscription, timer);
                });
        }

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

View on GitHub (pinned to 94b5d5ab91)