dotnet/reactive · error · ArgumentException

Delay cannot be less than zero

Error message

Delay cannot be less than zero

What it means

RefCount(source, disconnectDelay) requires a non-negative TimeSpan; a negative delay is meaningless for scheduling disconnection and throws ArgumentException with the message 'Delay cannot be less than zero'.

Solutions

  1. Clamp the delay to TimeSpan.Zero before calling: TimeSpan.FromTicks(Math.Max(0, delay.Ticks))
  2. Validate the configured delay when loading configuration
  3. Use TimeSpan.Zero if immediate disconnect is intended

Example fix

// before
var obs = conn.RefCount(TimeSpan.FromSeconds(-1));
// after
var delay = TimeSpan.FromSeconds(-1);
var obs = conn.RefCount(delay < TimeSpan.Zero ? TimeSpan.Zero : delay);
Defensive patterns

Strategy: validation

Validate before calling

if (disconnectDelay < TimeSpan.Zero) throw new ArgumentOutOfRangeException(nameof(disconnectDelay), disconnectDelay, "Delay cannot be less than zero");

Try / catch

try { var obs = conn.RefCount(delay); } catch (ArgumentException ex) when (ex.ParamName == "disconnectDelay") { delay = TimeSpan.Zero; }

Prevention

When it happens

Trigger: Passing TimeSpan values like TimeSpan.FromSeconds(-1), a computed delay that went negative (e.g. deadline already passed), or a config value parsed to a negative duration.

Common situations: Configuration files with negative timeout values, subtraction of timestamps yielding negative delays, or unit tests probing boundary values.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Binding.cs:259

        /// <summary>
        /// Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Connectable observable sequence.</param>
        /// <param name="disconnectDelay">The time span that should be waited before possibly unsubscribing from the connectable observable.</param>
        /// <returns>An observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        public static IObservable<TSource> RefCount<TSource>(this IConnectableObservable<TSource> source, TimeSpan disconnectDelay)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (disconnectDelay < TimeSpan.Zero)
            {
                throw new ArgumentException("Delay cannot be less than zero", nameof(disconnectDelay));
            }

            return s_impl.RefCount(source, disconnectDelay);
        }

        /// <summary>
        /// Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Connectable observable sequence.</param>
        /// <param name="disconnectDelay">The time span that should be waited before possibly unsubscribing from the connectable observable.</param>
        /// <param name="scheduler">The scheduler to use for delayed unsubscription.</param>
        /// <returns>An observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        public static IObservable<TSource> RefCount<TSource>(this IConnectableObservable<TSource> source, TimeSpan disconnectDelay, IScheduler scheduler)
        {
            if (source == null)
            {

View on GitHub (pinned to 94b5d5ab91)