dotnet/reactive · error · ArgumentNullException

fourth

Error message

fourth

What it means

Thrown by the 4-ary CombineLatest overload when the fourth source sequence is null. It is the final guard of the four null checks performed before first.Provider.CreateQuery builds the expression tree. Null is never accepted for a source argument in Qbservable operators.

Solutions

  1. Supply a non-null IObservable<TFourth> (Empty or Never as appropriate).
  2. Fix the code that leaves the fourth source null.
  3. Add a guard or default value before calling CombineLatest.

Example fix

// before
var combined = first.CombineLatest(s2, s3, fourth); // fourth null
// after
var combined = first.CombineLatest(s2, s3, fourth ?? Observable.Empty<TFourth>());
Defensive patterns

Strategy: validation

Validate before calling

if (fourth == null) fourth = Observable.Empty<TFourth>();

Type guard

static bool IsObservableSet<T>(IObservable<T> source) => source != null;

Try / catch

try { var combined = first.CombineLatest(second, third, fourth); } catch (ArgumentNullException ex) when (ex.ParamName == "fourth") { logger.LogError(ex, "Null fourth source passed to CombineLatest"); }

Prevention

When it happens

Trigger: Calling first.CombineLatest(second, third, fourth) with fourth == null, commonly from an optional stream variable that was never assigned.

Common situations: Feature-flagged streams absent at runtime; pipeline builders that skip populating the last source; test harnesses partially initializing arguments.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/QbservableEx.Homoicon.cs:104

        /// <typeparam name="TThird">The type of the elements in the third source sequence.</typeparam>
        /// <typeparam name="TFourth">The type of the elements in the fourth source sequence.</typeparam>
        /// <param name="first">First observable source.</param>
        /// <param name="second">Second observable source.</param>
        /// <param name="third">Third observable source.</param>
        /// <param name="fourth">Fourth observable source.</param>
        /// <returns>An observable sequence containing the result of combining elements of the sources using tuple values.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="first" /> or <paramref name="second" /> or <paramref name="third" /> or <paramref name="fourth" /> is null.</exception>
        public static IQbservable<(TFirst First, TSecond Second, TThird Third, TFourth Fourth)> CombineLatest<TFirst, TSecond, TThird, TFourth>(this IQbservable<TFirst> first, IObservable<TSecond> second, IObservable<TThird> third, IObservable<TFourth> fourth)
        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));
            if (third == null)
                throw new ArgumentNullException(nameof(third));
            if (fourth == null)
                throw new ArgumentNullException(nameof(fourth));

            return first.Provider.CreateQuery<(TFirst First, TSecond Second, TThird Third, TFourth Fourth)>(
                Expression.Call(
                    null,
                    new Func<IQbservable<TFirst>, IObservable<TSecond>, IObservable<TThird>, IObservable<TFourth>, IQbservable<(TFirst First, TSecond Second, TThird Third, TFourth Fourth)>>(CombineLatest<TFirst, TSecond, TThird, TFourth>).Method,
                    first.Expression,
                    GetSourceExpression(second),
                    GetSourceExpression(third),
                    GetSourceExpression(fourth)
                )
            );
        }

        /// <summary>
        /// Merges the specified observable sequences into one observable sequence of tuple values whenever any of the observable sequences produces an element.
        /// </summary>
        /// <typeparam name="TFirst">The type of the elements in the first source sequence.</typeparam>
        /// <typeparam name="TSecond">The type of the elements in the second source sequence.</typeparam>

View on GitHub (pinned to 94b5d5ab91)