dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

The Window(source, windowBoundaries) overload throws ArgumentNullException when the source observable is null (runtime message names parameter 'source'). Both the source and the boundary observable are validated synchronously; this guard covers the source.

Solutions

  1. Ensure the source is non-null before invoking Window.
  2. Have producers return AsyncObservable.Empty<T>() rather than null.
  3. Add a ThrowIfNull guard at the pipeline construction point.

Example fix

// before
var windows = BuildSource()?.Window(boundaries);
// after
var src = BuildSource() ?? AsyncObservable.Empty<Event>();
var windows = src.Window(boundaries);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) throw new ArgumentNullException(nameof(source));
var windows = source.Window(windowBoundaries);

Type guard

static bool IsSourceValid<TSource, B>(IAsyncObservable<TSource>? source, IAsyncObservable<B>? boundaries) => source is not null && boundaries is not null;

Try / catch

try { var windows = source.Window(boundaries); }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { /* rebuild source and retry */ }

Prevention

When it happens

Trigger: Calling source.Window(windowBoundaries) where source is null — usually an observable factory returning null on some code path, or an uninitialized field.

Common situations: Pipelines assembled from nullable steps; a helper returning IAsyncObservable<T> that can return null instead of an empty sequence; refactoring that removed an initialization.

Related errors


AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15). Data as JSON: /api/errors/7decd879027e9871. Report an issue: GitHub.

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Window.cs:139

            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (timeSpan < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(timeSpan));
            if (count <= 0)
                throw new ArgumentOutOfRangeException(nameof(count));
            if (scheduler == null)
                throw new ArgumentNullException(nameof(scheduler));

            return CreateAsyncObservable<IAsyncObservable<TSource>>.From(
                source,
                (timeSpan, count, scheduler),
                static (source, state, observer) => WindowAsyncCore(source, observer, (o, d) => AsyncObserver.Window(o, d, state.timeSpan, state.count, state.scheduler)));
        }

        public static IAsyncObservable<IAsyncObservable<TSource>> Window<TSource, TWindowBoundary>(this IAsyncObservable<TSource> source, IAsyncObservable<TWindowBoundary> windowBoundaries)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (windowBoundaries == null)
                throw new ArgumentNullException(nameof(windowBoundaries));

            return CreateAsyncObservable<IAsyncObservable<TSource>>.From(
                source,
                windowBoundaries,
                static async (source, windowBoundaries, observer) =>
                {
                    var d = new CompositeAsyncDisposable();

                    var (sourceObserver, boundariesObserver, subscription) = await AsyncObserver.Window<TSource, TWindowBoundary>(observer, d).ConfigureAwait(false);

                    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);

View on GitHub (pinned to 94b5d5ab91)