dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'windowClosingSelector')
Error message
Value cannot be null. (Parameter 'windowClosingSelector')
What it means
This ArgumentNullException is thrown by the Window<TSource,TWindowClosing> operator when the windowClosingSelector delegate is null. The selector is required to create each new window's closing observable, so the operator rejects a null selector immediately at call time. No subscription ever happens in this case.
Solutions
- Pass a non-null window-closing selector, e.g. () => AsyncObservable.Interval(TimeSpan.FromSeconds(5)).
- If the selector comes from a variable, initialize it before calling Window.
- Throw your own descriptive exception at the call site if the selector may legitimately be absent.
- Choose a different Window overload (count-based or time-based) if a closing selector isn't actually needed.
Example fix
// before Func<IAsyncObservable<long>> closing = null; var windows = source.Window(closing); // after var windows = source.Window(() => AsyncObservable.Interval(TimeSpan.FromSeconds(5)));
Defensive patterns
Strategy: validation
Validate before calling
if (windowClosingSelector is null) throw new ArgumentNullException(nameof(windowClosingSelector));
Type guard
bool IsValidSelector<TW>(Func<IAsyncObservable<TW>>? sel) => sel is not null;
Try / catch
try
{
var windows = source.Window(closingSelector);
}
catch (ArgumentNullException ex) when (ex.ParamName == "windowClosingSelector")
{
closingSelector = () => AsyncObservable.Interval(TimeSpan.FromSeconds(5));
} Prevention
- Pass method groups or lambdas directly instead of nullable delegate fields.
- Initialize delegate fields with a default selector at declaration time.
- Prefer the count/time-based Window overloads when no closing selector is needed.
When it happens
Trigger: Calling source.Window(null) on the parameterless overload, e.g. a Func<IAsyncObservable<TWindowClosing>> variable that was never assigned, or a conditional expression that resolved to null.
Common situations: Passing a method group that doesn't match an overload and binding to null instead; storing the selector in a nullable field initialized after use; refactoring that removed the lambda but left the call.
Related errors
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'windowBoundaries')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'subscription')
- nameof(finallyAction)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/a347d30f25a8212c.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Window.cs:169
var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
await d.AddAsync(sourceSubscription).ConfigureAwait(false);
var boundariesSubscription = await windowBoundaries.SubscribeSafeAsync(boundariesObserver).ConfigureAwait(false);
await d.AddAsync(boundariesSubscription).ConfigureAwait(false);
return subscription;
});
}
// REVIEW: This overload is inherited from Rx but arguably a bit esoteric as it doesn't provide context to the closing selector.
public static IAsyncObservable<IAsyncObservable<TSource>> Window<TSource, TWindowClosing>(this IAsyncObservable<TSource> source, Func<IAsyncObservable<TWindowClosing>> windowClosingSelector)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (windowClosingSelector == null)
throw new ArgumentNullException(nameof(windowClosingSelector));
return CreateAsyncObservable<IAsyncObservable<TSource>>.From(
source,
windowClosingSelector,
static async (source, windowClosingSelector, observer) =>
{
var d = new CompositeAsyncDisposable();
var (sourceObserver, closingSubscription, subscription) = await AsyncObserver.Window<TSource, TWindowClosing>(observer, windowClosingSelector, d).ConfigureAwait(false);
await d.AddAsync(closingSubscription).ConfigureAwait(false);
var sourceSubscription = await source.SubscribeSafeAsync(sourceObserver).ConfigureAwait(false);
await d.AddAsync(sourceSubscription).ConfigureAwait(false);
return subscription;
});
}View on GitHub (pinned to 94b5d5ab91)