dotnet/reactive · error · ArgumentNullException

ArgumentNullException(nameof(first))

Error message

ArgumentNullException(nameof(first))

What it means

Concat<TSource>(first, second) throws ArgumentNullException when the first observable is null (Observable.Multiple.cs:357). Rx checks arguments eagerly and in order, so this fires before the second-source check. The error is thrown synchronously at the call site rather than being delivered through OnError.

Solutions

  1. Initialize the first observable before concatenating; use Observable.Empty<TSource>() when there is genuinely nothing to emit.
  2. Coalesce: (first ?? Observable.Empty<TSource>()).Concat(second).
  3. Fix the upstream producer so it returns an empty observable instead of null.

Example fix

// before
IObservable<Event> history = LoadHistory(); // can return null
var all = history.Concat(live);
// after
var all = (LoadHistory() ?? Observable.Empty<Event>()).Concat(live);
Defensive patterns

Strategy: validation

Validate before calling

if (first == null) throw new InvalidOperationException("first source required"); // or: first ??= Observable.Empty<TSource>();

Type guard

bool IsStreamReady(IObservable<TSource>? first) => first is not null;

Try / catch

try { var result = first.Concat(second); } catch (ArgumentNullException ex) when (ex.ParamName == "first") { /* fall back to Observable.Empty<TSource>() */ }

Prevention

When it happens

Trigger: Calling first.Concat(second) or Observable.Concat(first, second) where the first IObservable is null.

Common situations: First stream from an uninitialized Subject or an unregistered event bus lookup; a factory returning null when a feature is disabled; chained pipeline code where an earlier stage produced null instead of an empty observable.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.cs:357

        }

        #endregion

        #region + Concat +

        /// <summary>
        /// Concatenates the second observable sequence to the first observable sequence upon successful termination of the first.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
        /// <param name="first">First observable sequence.</param>
        /// <param name="second">Second observable sequence.</param>
        /// <returns>An observable sequence that contains the elements of the first sequence, followed by those of the second the sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="first"/> or <paramref name="second"/> is null.</exception>
        public static IObservable<TSource> Concat<TSource>(this IObservable<TSource> first, IObservable<TSource> second)
        {
            if (first == null)
            {
                throw new ArgumentNullException(nameof(first));
            }

            if (second == null)
            {
                throw new ArgumentNullException(nameof(second));
            }

            return s_impl.Concat(first, second);
        }

        /// <summary>
        /// Concatenates all of the specified observable sequences, as long as the previous observable sequence terminated successfully.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequences.</typeparam>
        /// <param name="sources">Observable sequences to concatenate.</param>
        /// <returns>An observable sequence that contains the elements of each given sequence, in sequential order.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="sources"/> is null.</exception>
        public static IObservable<TSource> Concat<TSource>(params IObservable<TSource>[] sources)

View on GitHub (pinned to 94b5d5ab91)