dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'source')
Error message
Value cannot be null. (Parameter 'source')
What it means
The time-based Buffer(source, timeSpan) operator in Observable.Time.cs validates the source observable first and throws ArgumentNullException when it is null. Time-based operators additionally need the source to schedule buffer windows, so a null source is rejected immediately before any scheduling setup.
Solutions
- Ensure the upstream producer returns Observable.Empty<T>() or a valid observable instead of null.
- Coalesce before buffering: `(source ?? Observable.Empty<T>()).Buffer(timeSpan)`.
- Validate inputs at service construction so the null is caught long before the Rx chain runs.
Example fix
// before var windows = telemetry.Buffer(TimeSpan.FromSeconds(5)); // telemetry == null // after var windows = (telemetry ?? Observable.Empty<Metric>()).Buffer(TimeSpan.FromSeconds(5));
Defensive patterns
Strategy: validation
Validate before calling
if (source is null) source = Observable.Empty<TSource>(); // before time-based Buffer if (timeSpan < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(timeSpan));
Type guard
bool HasSource<T>(IObservable<T>? s) => s is not null;
Try / catch
try { var r = src.Buffer(timeSpan); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* use Observable.Empty<T>() */ } Prevention
- Ensure event/telemetry stream producers never return null.
- Coalesce nullable streams before time-windowed operators.
- Validate composed pipelines in constructor or startup checks.
When it happens
Trigger: Calling source.Buffer(TimeSpan.FromSeconds(1)) where source is null — e.g. a null-returning producer, an unset event-to-observable conversion result, or a DI dependency not registered.
Common situations: Event streams built from Observable.FromEventPattern where the backing hookup returned null; timers/telemetry streams that are conditionally created; null scheduler/source fields in services composing time-windowed pipelines.
Related errors
- Value cannot be null. (Parameter 'source9')
- Value cannot be null. (Parameter 'bufferOpenings')
- Value cannot be null. (Parameter 'bufferBoundaries')
- Value cannot be null. (Parameter 'scheduler')
- throw new…
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/42220fbd5c58886c.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Time.cs:34
/// <summary>
/// Projects each element of an observable sequence into consecutive non-overlapping buffers which are produced based on timing information.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence, and in the lists in the result sequence.</typeparam>
/// <param name="source">Source sequence to produce buffers over.</param>
/// <param name="timeSpan">Length of each buffer.</param>
/// <returns>An observable sequence of buffers.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
/// <exception cref="ArgumentOutOfRangeException"><paramref name="timeSpan"/> is less than TimeSpan.Zero.</exception>
/// <remarks>
/// Specifying a TimeSpan.Zero value for <paramref name="timeSpan"/> is not recommended but supported, causing the scheduler to create buffers as fast as it can.
/// Because all source sequence elements end up in one of the buffers, some buffers won't have a zero time span. This is a side-effect of the asynchrony introduced
/// by the scheduler, where the action to close the current buffer and to create a new buffer may not execute immediately, despite the TimeSpan.Zero due time.
/// </remarks>
public static IObservable<IList<TSource>> Buffer<TSource>(this IObservable<TSource> source, TimeSpan timeSpan)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (timeSpan < TimeSpan.Zero)
{
throw new ArgumentOutOfRangeException(nameof(timeSpan));
}
return s_impl.Buffer(source, timeSpan);
}
/// <summary>
/// Projects each element of an observable sequence into consecutive non-overlapping buffers which are produced based on timing information, using the specified scheduler to run timers.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence, and in the lists in the result sequence.</typeparam>
/// <param name="source">Source sequence to produce buffers over.</param>
/// <param name="timeSpan">Length of each buffer.</param>
/// <param name="scheduler">Scheduler to run buffering timers on.</param>
/// <returns>An observable sequence of buffers.</returns>View on GitHub (pinned to 94b5d5ab91)