dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'second')

Error message

Value cannot be null. (Parameter 'second')

What it means

AsyncObservable.Concat<TSource>(first, second) throws ArgumentNullException naming 'second' when the second observable is null. The guard fires immediately at the call site rather than when the sequence is subscribed.

Solutions

  1. Pass a non-null IAsyncObservable<TSource> as the second argument
  2. Use AsyncObservable.Empty<TSource>() when the continuation is absent
  3. Verify the code path that constructs 'second' and handle its null case before Concat

Example fix

// before
var result = main.Concat(continuation); // continuation is null
// after
var result = main.Concat(continuation ?? AsyncObservable.Empty<int>());
Defensive patterns

Strategy: validation

Validate before calling

if (second is null) throw new ArgumentNullException(nameof(second)); // or second ??= AsyncObservable.Empty<T>();

Type guard

public static bool IsNotNullSource<T>(IAsyncObservable<T>? s) => s is not null;

Try / catch

try { var result = first.Concat(second); }
catch (ArgumentNullException ex) when (ex.ParamName == "second") { /* supply a valid continuation or Empty<T>() */ }

Prevention

When it happens

Trigger: Calling Concat(first, null), typically when the second observable comes from a nullable source such as a config-selected provider, optional cache, or failed lookup.

Common situations: Conditional continuation logic where the 'next' observable is only sometimes produced; merging a primary stream with an optional fallback stream that resolved to null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Concat.cs:20

// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Collections.Generic;
using System.Reactive.Disposables;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    // TODO: Implement tail call behavior to flatten Concat chains.

    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> Concat<TSource>(this IAsyncObservable<TSource> first, IAsyncObservable<TSource> second)
        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));

            return Create(
                first,
                second,
                static async (first, second, observer) =>
                {
                    var (sink, inner) = AsyncObserver.Concat(observer, second);

                    var subscription = await first.SubscribeSafeAsync(sink).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(subscription, inner);
                });
        }

        public static IAsyncObservable<TSource> Concat<TSource>(params IAsyncObservable<TSource>[] sources) => Concat((IEnumerable<IAsyncObservable<TSource>>)sources);

        public static IAsyncObservable<TSource> Concat<TSource>(this IEnumerable<IAsyncObservable<TSource>> sources)
        {

View on GitHub (pinned to 94b5d5ab91)