dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'bufferOpenings')
Error message
Value cannot be null. (Parameter 'bufferOpenings')
What it means
The Buffer(source, bufferOpenings, bufferClosingSelector) overload requires a non-null bufferOpenings observable that signals when each buffer starts. Passing null for bufferOpenings throws ArgumentNullException at call time. The library validates arguments eagerly so the failure surfaces at the call site, not inside the subscription.
Solutions
- Initialize or fix the bufferOpenings observable so it is non-null before calling Buffer.
- Substitute Observable.Empty<TBufferOpening>() when there are genuinely no openings (yields no buffers).
- Guard the call: only invoke Buffer when both source and openings streams are available.
Example fix
// before var buffers = source.Buffer(maybeOpenings, x => closings); // throws if maybeOpenings is null // after var openings = maybeOpenings ?? Observable.Empty<Opening>(); var buffers = source.Buffer(openings, x => closings);
Defensive patterns
Strategy: validation
Validate before calling
ArgumentNullException.ThrowIfNull(openings); var openings = maybeOpenings ?? Observable.Empty<TBufferOpening>();
Type guard
bool HasOpenings<TBufferOpening>(IObservable<TBufferOpening>? openings) => openings is not null;
Try / catch
try { var buffers = source.Buffer(openings, closingSelector); }
catch (ArgumentNullException ex) when (ex.ParamName == "bufferOpenings") { /* supply Observable.Empty<TBufferOpening>() */ } Prevention
- Never return null for an event/opening stream; return Observable.Empty or Observable.Never.
- Wire opening subjects/streams during initialization before any operator is composed.
- Use nullable annotations on fields holding boundary streams to catch missing wiring.
When it happens
Trigger: Calling source.Buffer(openings, selector) where the openings IObservable<TBufferOpening> is null — e.g. an event stream that was never wired up, a Subject that failed to initialize, or a null result from a lookup of opening events.
Common situations: Dynamic UI/event wiring where the opening-signal stream is conditionally created; a service returning null instead of Observable.Empty for the opening stream; copy-pasted operator calls where the openings argument was accidentally dropped or left as an uninitialized variable.
Related errors
- Value cannot be null. (Parameter 'bufferBoundaries')
- Specified argument was out of the range of valid values…
- Value cannot be null. (Parameter 'handler')
- Value cannot be null. (Parameter 'source')
- throw new ArgumentNullException(nameof(condition));
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/3bc6a9b6332d6c68.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.cs:124
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence, and in the lists in the result sequence.</typeparam>
/// <typeparam name="TBufferOpening">The type of the elements in the sequence indicating buffer opening events, also passed to the closing selector to obtain a sequence of buffer closing events.</typeparam>
/// <typeparam name="TBufferClosing">The type of the elements in the sequences indicating buffer closing events.</typeparam>
/// <param name="source">Source sequence to produce buffers over.</param>
/// <param name="bufferOpenings">Observable sequence whose elements denote the creation of new buffers.</param>
/// <param name="bufferClosingSelector">A function invoked to define the closing of each produced buffer.</param>
/// <returns>An observable sequence of buffers.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="bufferOpenings"/> or <paramref name="bufferClosingSelector"/> is null.</exception>
public static IObservable<IList<TSource>> Buffer<TSource, TBufferOpening, TBufferClosing>(this IObservable<TSource> source, IObservable<TBufferOpening> bufferOpenings, Func<TBufferOpening, IObservable<TBufferClosing>> bufferClosingSelector)
{
if (source == null)
{
throw new ArgumentNullException(nameof(source));
}
if (bufferOpenings == null)
{
throw new ArgumentNullException(nameof(bufferOpenings));
}
if (bufferClosingSelector == null)
{
throw new ArgumentNullException(nameof(bufferClosingSelector));
}
return s_impl.Buffer(source, bufferOpenings, bufferClosingSelector);
}
/// <summary>
/// Projects each element of an observable sequence into consecutive non-overlapping buffers.
/// </summary>
/// <typeparam name="TSource">The type of the elements in the source sequence, and in the lists in the result sequence.</typeparam>
/// <typeparam name="TBufferBoundary">The type of the elements in the sequences indicating buffer boundary events.</typeparam>
/// <param name="source">Source sequence to produce buffers over.</param>
/// <param name="bufferBoundaries">Sequence of buffer boundary markers. The current buffer is closed and a new buffer is opened upon receiving a boundary marker.</param>
/// <returns>An observable sequence of buffers.</returns>View on GitHub (pinned to 94b5d5ab91)