dotnet/reactive · error · ArgumentOutOfRangeException

ArgumentOutOfRangeException (default message: Specified…

Error message

ArgumentOutOfRangeException (default message: Specified argument was out of the range of valid values. (Parameter 'count'))

What it means

SkipLast bypasses a number of trailing elements; the documented ArgumentOutOfRangeException fires when count is less than zero, since a negative bypass count is invalid. Fix: pass 0 or a positive count.

Solutions

  1. Clamp with Math.Max(0, count) before calling.
  2. Validate the numeric input at the configuration boundary.
  3. Fix the subtraction/logic producing the negative count.
  4. Use SkipLast(0) explicitly when 'skip nothing' is the intent.

Example fix

// before
var result = source.SkipLast(take - skip);
// after
var result = source.SkipLast(Math.Max(0, take - skip));
Defensive patterns

Strategy: validation

Validate before calling

if (count < 0) throw new ArgumentOutOfRangeException(nameof(count));
var result = source.SkipLast(count);

Type guard

bool IsValidCount(int n) => n >= 0;

Try / catch

try { result = source.SkipLast(n); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "count") { result = source; }

Prevention

When it happens

Trigger: Calling SkipLast(source, count) where count < 0, typically a computed value like `take - skip` or an unvalidated user/config value.

Common situations: Arithmetic on counts where the subtracted value exceeds the taken value; config or CLI-supplied sizes parsed without range validation.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Single.cs:770

        /// <param name="source">Source sequence.</param>
        /// <param name="count">Number of elements to bypass at the end of the source sequence.</param>
        /// <returns>An observable sequence containing the source sequence elements except for the bypassed ones at the end.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="count"/> is less than zero.</exception>
        /// <remarks>
        /// This operator accumulates a queue with a length enough to store the first <paramref name="count"/> elements. As more elements are
        /// received, elements are taken from the front of the queue and produced on the result sequence. This causes elements to be delayed.
        /// </remarks>
        public static IObservable<TSource> SkipLast<TSource>(this IObservable<TSource> source, int count)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (count < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(count));
            }

            return s_impl.SkipLast(source, count);
        }

        #endregion

        #region + StartWith +

        /// <summary>
        /// Prepends a sequence of values to an observable sequence.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence to prepend values to.</param>
        /// <param name="values">Values to prepend to the specified sequence.</param>
        /// <returns>The source sequence prepended with the specified values.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="values"/> is null.</exception>
        public static IObservable<TSource> StartWith<TSource>(this IObservable<TSource> source, params TSource[] values)

View on GitHub (pinned to 94b5d5ab91)