dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'subscription')
Error message
Value cannot be null. (Parameter 'subscription')
What it means
This ArgumentNullException is thrown by the count-based Window helper when the subscription IAsyncDisposable is null. The subscription represents the upstream disposable and is wrapped in a RefCountAsyncDisposable, so a null value cannot be accepted. It fails fast at the call, before any windows are created.
Solutions
- Create and pass a real disposable, e.g. new CompositeAsyncDisposable(), before calling Window.
- Pass the disposable you obtained from the upstream SubscribeAsync call.
- Use AsyncDisposable.Nop / an empty composite if no upstream subscription exists yet.
- Add a null check in your wrapper so the error points at your call site.
Example fix
// before var (winObs, disp) = WindowOperators.Window<TSource>(observer, null, 5); // after var d = new CompositeAsyncDisposable(); var (winObs, disp) = WindowOperators.Window<TSource>(observer, d, 5);
Defensive patterns
Strategy: validation
Validate before calling
if (subscription is null) throw new ArgumentNullException(nameof(subscription)); // or: subscription ??= AsyncDisposable.Nop;
Type guard
bool IsValidDisposable(IAsyncDisposable? d) => d is not null;
Try / catch
try
{
var (winObs, disp) = WindowOperators.Window<TSource>(observer, subscription, count);
}
catch (ArgumentNullException ex) when (ex.ParamName == "subscription")
{
subscription = new CompositeAsyncDisposable();
} Prevention
- Create the upstream/CompositeAsyncDisposable before calling operator helpers.
- Forward the disposable from SubscribeAsync results directly.
- Use AsyncDisposable.Nop as an explicit 'no resource' value instead of null.
When it happens
Trigger: Calling Window(observer, null, count) or Window(observer, null, count, skip) — usually when wiring a custom operator and the upstream disposable hasn't been created yet.
Common situations: Custom operator implementations where the CompositeAsyncDisposable is created after the helper call; test harnesses passing null disposables; reordering refactors in operator plumbing.
Related errors
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'windowBoundaries')
- Value cannot be null. (Parameter 'windowClosingSelector')
- Value cannot be null. (Parameter 'observer')
- nameof(finallyAction)
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/127b9f1fe8cf12ae.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Window.cs:223
var (sink, subscription) = await createObserverAsync(observer, d).ConfigureAwait(false);
var inner = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);
await d.AssignAsync(inner).ConfigureAwait(false);
return subscription;
}
}
public partial class AsyncObserver
{
public static (IAsyncObserver<TSource>, IAsyncDisposable) Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, int count) => Window(observer, subscription, count, count);
public static (IAsyncObserver<TSource>, IAsyncDisposable) Window<TSource>(IAsyncObserver<IAsyncObservable<TSource>> observer, IAsyncDisposable subscription, int count, int skip)
{
if (observer == null)
throw new ArgumentNullException(nameof(observer));
if (subscription == null)
throw new ArgumentNullException(nameof(subscription));
if (count <= 0)
throw new ArgumentOutOfRangeException(nameof(count));
if (skip <= 0)
throw new ArgumentOutOfRangeException(nameof(skip));
var refCount = new RefCountAsyncDisposable(subscription);
var queue = new Queue<IAsyncSubject<TSource>>();
var n = 0;
return
(
Create<TSource>
(
async x =>
{
foreach (var window in queue)
{View on GitHub (pinned to 94b5d5ab91)