dotnet/reactive · error · ArgumentOutOfRangeException

throw new ArgumentOutOfRangeException(nameof(dueTime));

Error message

throw new ArgumentOutOfRangeException(nameof(dueTime));

What it means

Throttle throws ArgumentOutOfRangeException when dueTime is negative (less than TimeSpan.Zero). A negative quiet period has no meaning for the underlying scheduler delay, so the library rejects it at call time.

Solutions

  1. Clamp or validate the delay before calling: if (ts < TimeSpan.Zero) ts = TimeSpan.Zero
  2. Fix the calculation producing the negative TimeSpan
  3. Validate user/config-provided debounce values at load time

Example fix

// before
var due = end - start; // can be negative
var throttled = AsyncObservable.Throttle(source, due);
// after
var due = end - start;
if (due < TimeSpan.Zero) due = TimeSpan.Zero;
var throttled = AsyncObservable.Throttle(source, due);
Defensive patterns

Strategy: validation

Validate before calling

if (dueTime < TimeSpan.Zero)
    throw new ArgumentOutOfRangeException(nameof(dueTime));
var throttled = AsyncObservable.Throttle(source, dueTime);

Type guard

static bool IsValidDueTime(TimeSpan t) => t >= TimeSpan.Zero;

Try / catch

try { var throttled = AsyncObservable.Throttle(source, due); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "dueTime") { due = TimeSpan.Zero; }

Prevention

When it happens

Trigger: Calling AsyncObservable.Throttle(source, TimeSpan.FromSeconds(-1)) or computing a delay from data that can go negative (e.g. subtraction of timestamps, user-provided negative input).

Common situations: Parsing a debounce interval from config/user input without validating sign; computing dueTime as targetTime - now after the target already passed; unit tests with sentinel negative values.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Throttle.cs:18

// 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.Reactive.Concurrency;
using System.Reactive.Disposables;
using System.Threading;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> Throttle<TSource>(this IAsyncObservable<TSource> source, TimeSpan dueTime)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (dueTime < TimeSpan.Zero)
                throw new ArgumentOutOfRangeException(nameof(dueTime));

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

                    var (sink, throttler) = AsyncObserver.Throttle(observer, dueTime);

                    await d.AddAsync(throttler).ConfigureAwait(false);

                    var sourceSubscription = await source.SubscribeSafeAsync(sink).ConfigureAwait(false);

                    await d.AddAsync(sourceSubscription).ConfigureAwait(false);

                    return d;
                });

View on GitHub (pinned to 94b5d5ab91)