dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'first')

Error message

Value cannot be null. (Parameter 'first')

What it means

WithLatestFrom combines a source observable (first) with the latest value from another observable (second) as they arrive. The extension method validates its receiver/argument and throws ArgumentNullException with parameter name 'first' when the first (source) IAsyncObservable<TFirst> is null, failing fast before any subscription machinery is created.

Solutions

  1. Ensure the source observable assigned to `first` is created (e.g. via AsyncObservable.CreateAsyncObservable...) before chaining.
  2. Check whether an earlier operator in the chain can return null and fix it to throw or return a valid observable.
  3. Add a null check at pipeline construction time with a descriptive message.
  4. If the source is optional by design, substitute an empty observable instead of null.

Example fix

// before
IAsyncObservable<int> first = GetMaybeNullSource();
var result = first.WithLatestFrom(second);
// after
var result = (first ?? AsyncObservable.Empty<int>()).WithLatestFrom(second);
Defensive patterns

Strategy: validation

Validate before calling

if (first is null) throw new ArgumentNullException(nameof(first));
var result = first.WithLatestFrom(second);

Type guard

bool IsSourceValid<T>(IAsyncObservable<T> o) => o is not null;

Try / catch

try
{
    var result = first.WithLatestFrom(second);
}
catch (ArgumentNullException ex) when (ex.ParamName == "first")
{
    // fall back to an empty source pipeline
    var result = AsyncObservable.Empty<TFirst>().WithLatestFrom(second);
}

Prevention

When it happens

Trigger: Invoking first.WithLatestFrom(second) where the receiver `first` is null, e.g. chaining off a pipeline variable that was never assigned or a factory method that returned null.

Common situations: Chained pipeline construction where an earlier operator returned null instead of an observable; configuration-driven pipelines where the primary source was not wired; unit tests building the chain with a null placeholder.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/WithLatestFrom.cs:16

// Licensed to the .NET Foundation under one or more agreements.
// 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.Reactive.Disposables;
using System.Threading;
using System.Threading.Tasks;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<(TFirst first, TSecond second)> WithLatestFrom<TFirst, TSecond>(this IAsyncObservable<TFirst> first, IAsyncObservable<TSecond> second)
        {
            if (first == null)
                throw new ArgumentNullException(nameof(first));
            if (second == null)
                throw new ArgumentNullException(nameof(second));

            return CreateAsyncObservable<(TFirst first, TSecond second)>.From(
                first,
                second,
                static async (first, second, observer) =>
                {
                    var (firstObserver, secondObserver) = AsyncObserver.WithLatestFrom(observer);

                    // REVIEW: Consider concurrent subscriptions.

                    var firstSubscription = await first.SubscribeSafeAsync(firstObserver).ConfigureAwait(false);
                    var secondSubscription = await second.SubscribeSafeAsync(secondObserver).ConfigureAwait(false);

                    return StableCompositeAsyncDisposable.Create(firstSubscription, secondSubscription);
                });
        }

View on GitHub (pinned to 94b5d5ab91)