dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

AsyncObserver.Concat<TSource>(observer, second) throws ArgumentNullException naming 'observer' when the downstream observer is null. This factory wires a continuation observer that resubscribes to 'second' after the current sequence completes, so a valid observer is mandatory.

Solutions

  1. Pass a non-null IAsyncObserver<TSource> as the observer argument
  2. Check how the observer is created and propagated in your custom operator/sink code
  3. Use SubscribeSafeAsync on a real observable rather than manually constructing observer sinks when possible

Example fix

// before
var (sink, disp) = AsyncObserver.Concat(observer, second); // observer is null
// after
if (observer == null) throw new InvalidOperationException("observer not initialized");
var (sink, disp) = AsyncObserver.Concat(observer, second);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));

Type guard

public static bool HasObserver<T>(IAsyncObserver<T>? o) => o is not null;

Try / catch

try { var (sink, disp) = AsyncObserver.Concat(observer, second); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* initialize observer before building sink */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.Concat(null, second) when hand-rolling operators or sinks, e.g. passing an observer field that was never initialized.

Common situations: Custom operator implementations where the observer is threaded through several constructors and arrives null due to a wiring/ordering bug.

Related errors


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

Appendix: source

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

                }

                var source = enumerator.Current;

                var (sink, inner) = AsyncObserver.Concat(observer, enumerator);

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

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

    public partial class AsyncObserver
    {
        public static (IAsyncObserver<TSource>, IAsyncDisposable) Concat<TSource>(IAsyncObserver<TSource> observer, IAsyncObservable<TSource> second)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (second == null)
                throw new ArgumentNullException(nameof(second));

            var subscription = new SingleAssignmentAsyncDisposable();

            var sink = Create<TSource>(
                observer.OnNextAsync,
                observer.OnErrorAsync,
                async () =>
                {
                    var secondSubscription = await second.SubscribeSafeAsync(observer).ConfigureAwait(false);

                    await subscription.AssignAsync(secondSubscription).ConfigureAwait(false);
                }
            );

            return (sink, subscription);
        }

View on GitHub (pinned to 94b5d5ab91)