dotnet/reactive · error · ArgumentNullException

observer

Error message

observer

What it means

AsyncObserver.Select (sync, non-indexed) validates its downstream IAsyncObserver<TResult> and throws ArgumentNullException named 'observer' when it is null. This guards the internal operator composition path so a null downstream observer is rejected immediately.

Solutions

  1. Always pass a real IAsyncObserver<TResult>, e.g. one obtained from Create or a downstream operator
  2. Assert non-null upstream before composing: ArgumentNullException.ThrowIfNull(observer)
  3. If downstream may be absent, use a no-op observer implementation instead of null

Example fix

// before
var obs = AsyncObserver.Select<int, int>(null, x => x * 2);
// after
var downstream = AsyncObserver.Create<int>(async x => Console.WriteLine(x));
var obs = AsyncObserver.Select<int, int>(downstream, x => x * 2);
Defensive patterns

Strategy: validation

Validate before calling

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

Type guard

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

Try / catch

try { var obs = AsyncObserver.Select<int, int>(downstream, x => x); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* create or substitute downstream observer */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.Select<TSource,TResult>(null, x => result) directly, usually when composing custom operators or wiring observers manually.

Common situations: Custom operator builders that pass a not-yet-created observer; refactoring where the downstream observer variable became null; testing operator internals with null observers.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Select.cs:69

        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));

            return CreateAsyncObservable<TResult>.From(
                source,
                selector,
                static (source, selector, observer) => source.SubscribeSafeAsync(AsyncObserver.Select(observer, selector)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> Select<TSource, TResult>(IAsyncObserver<TResult> observer, Func<TSource, TResult> selector)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (selector == null)
                throw new ArgumentNullException(nameof(selector));

            return Create<TSource>(
                async x =>
                {
                    TResult res;

                    try
                    {
                        res = selector(x);
                    }
                    catch (Exception ex)
                    {
                        await observer.OnErrorAsync(ex).ConfigureAwait(false);
                        return;
                    }

View on GitHub (pinned to 94b5d5ab91)