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
- Ensure the TimeSpan is >= TimeSpan.Zero before calling; clamp: if (ts < TimeSpan.Zero) ts = TimeSpan.Zero; (or a sensible positive default).
- Fix the computation producing the negative duration (e.g. clamp end >= start before subtracting).
- 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
- Clamp clock-derived durations: window = end > start ? end - start : TimeSpan.Zero
- Never use negative TimeSpans as 'unset' sentinels without validating first
- Validate configured durations at startup
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
- Value cannot be null. (Parameter 'count')
- Value cannot be null. (Parameter 'skip')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
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)