dotnet/reactive · error · ArgumentNullException

ArgumentNullException

Error message

ArgumentNullException

What it means

Window<TSource>(source, count) splits the source into windows of at most count elements; the library throws ArgumentNullException when the source is null. This eager check is standard across AsyncRx operators so misuse is caught at composition time, not at subscription.

Solutions

  1. Check that the receiver/source is non-null before calling Window.
  2. Replace a null source with AsyncObservable.Empty<TSource>() when absence is acceptable.
  3. Move the null check upstream to whoever produces the source.
  4. Use the null-forgiving/nullable-flow analysis (enable NRT warnings) so null sources are caught at compile time.

Example fix

// before
var windows = maybeSource.Window(3); // maybeSource is null
// after
var windows = (maybeSource ?? AsyncObservable.Empty<int>()).Window(3);
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) throw new InvalidOperationException("Cannot window a null source");
if (count <= 0) throw new InvalidOperationException("Window count must be positive");
var windows = source.Window(count);

Type guard

static bool CanWindow<TSource>(IAsyncObservable<TSource>? source, int count)
    => source is not null && count > 0;

Try / catch

try { var windows = source.Window(count); }
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    // handle missing source (log, substitute empty, or rethrow with context)
}

Prevention

When it happens

Trigger: Calling source.Window(count) via extension syntax with a null receiver, or AsyncObservable.Window(null, 5).

Common situations: Chaining off a query result that came back null; a nullable source variable not checked before composing the pipeline; source produced by an external factory with a null result.

Related errors


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

Appendix: source

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

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Collections.Generic;
using System.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Reactive.Subjects;
using System.Threading;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<IAsyncObservable<TSource>> Window<TSource>(this IAsyncObservable<TSource> source, int count)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (count <= 0)
                throw new ArgumentOutOfRangeException(nameof(count));

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

        public static IAsyncObservable<IAsyncObservable<TSource>> Window<TSource>(this IAsyncObservable<TSource> source, int count, int skip)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (count <= 0)
                throw new ArgumentOutOfRangeException(nameof(count));
            if (skip <= 0)
                throw new ArgumentOutOfRangeException(nameof(skip));

View on GitHub (pinned to 94b5d5ab91)