dotnet/reactive · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException

Error message

ArgumentOutOfRangeException

What it means

Window<TSource>(source, count) requires count to be strictly positive; count <= 0 raises ArgumentOutOfRangeException. A non-positive window size is meaningless (an empty window can never complete), so the library rejects it eagerly.

Solutions

  1. Pass a count >= 1; clamp with Math.Max(1, requestedCount) if the value is configurable.
  2. Validate configuration values at load time and reject non-positive batch/window sizes with a clear message.
  3. Check the computation producing count for off-by-one or sign errors.
  4. If callers may pass 0 meaning 'no windowing', branch to skip the Window operator instead of calling it.

Example fix

// before
var windows = source.Window(config.WindowSize); // may be 0
// after
if (config.WindowSize <= 0) throw new InvalidOperationException("WindowSize must be positive");
var windows = source.Window(config.WindowSize);
Defensive patterns

Strategy: validation

Validate before calling

if (count <= 0)
    throw new ArgumentOutOfRangeException(nameof(count), "Window size must be at least 1");
var windows = source.Window(count);

Type guard

static bool IsValidWindowSize(int count) => count > 0;

Try / catch

try { var windows = source.Window(count); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "count")
{
    var windows = source.Window(1); // or handle invalid config
}

Prevention

When it happens

Trigger: Calling source.Window(0), source.Window(-1), or with a count computed from unvalidated input (config value, parsed string) that is <= 0.

Common situations: Reading a batch-size setting from configuration that defaults to 0; subtracting offsets and passing a negative remainder; hard-coding a size then changing semantics so it can be zero for 'disabled'.

Related errors


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

Appendix: source

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

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

            return CreateAsyncObservable<IAsyncObservable<TSource>>.From(
                source,

View on GitHub (pinned to 94b5d5ab91)