dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'first')

Error message

Value cannot be null. (Parameter 'first')

What it means

The two-sequence overload Catch<TSource>(first, second) throws ArgumentNullException with parameter name 'first' when the first (extension receiver) sequence is null. The operator concatenates first with second as an error fallback, so both sequences must be non-null; validation happens eagerly at call time.

Solutions

  1. Ensure the first sequence is non-null; use Enumerable.Empty<TSource>() if there is no data.
  2. Coalesce at the call site: (first ?? Enumerable.Empty<T>()).Catch(second).
  3. Fix the upstream method to return an empty sequence rather than null.
  4. Enable nullable reference types so the compiler warns before the call.

Example fix

// before
var result = ((IEnumerable<int>)null).Catch(fallback);
// after
var result = (first ?? Enumerable.Empty<int>()).Catch(fallback);
Defensive patterns

Strategy: validation

Validate before calling

if (first is null)
    throw new ArgumentNullException(nameof(first));
// or coalesce at the call site:
var result = (first ?? Enumerable.Empty<TSource>()).Catch(second);

Type guard

static bool IsUsableSource<TSource>(IEnumerable<TSource> s) => s != null;

Try / catch

try
{
    var result = first.Catch(second);
}
catch (ArgumentNullException ex) when (ex.ParamName == "first")
{
    var result = second;
}

Prevention

When it happens

Trigger: Calling first.Catch(second) where the first sequence is null, e.g. the result of a prior operation that can return null.

Common situations: A data-access method returning null instead of an empty sequence; an optional field used directly as the primary sequence; pipeline wiring where an earlier operator produced null.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Catch.cs:69

        public static IEnumerable<TSource> Catch<TSource>(params IEnumerable<TSource>[] sources)
        {
            if (sources == null)
                throw new ArgumentNullException(nameof(sources));

            return CatchCore(sources);
        }

        /// <summary>
        /// Creates a sequence that returns the elements of the first sequence, switching to the second in case of an error.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <param name="first">First sequence.</param>
        /// <param name="second">Second sequence, concatenated to the result in case the first sequence completes exceptionally.</param>
        /// <returns>The first sequence, followed by the second sequence in case an error is produced.</returns>
        public static IEnumerable<TSource> Catch<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second)
        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));

            return CatchCore(new[] { first, second });
        }

        private static IEnumerable<TSource> CatchCore<TSource, TException>(IEnumerable<TSource> source, Func<TException, IEnumerable<TSource>> handler)
            where TException : Exception
        {
            var err = default(IEnumerable<TSource>);

            using (var e = source.GetEnumerator())
            {
                while (true)
                {
                    TSource c;

                    try

View on GitHub (pinned to 94b5d5ab91)