dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'observer')

Error message

Value cannot be null. (Parameter 'observer')

What it means

AsyncObserver.Synchronize(observer) wraps an observer so its callbacks are serialized under a new AsyncGate. A null observer cannot be wrapped, so the method throws ArgumentNullException immediately. This overload allocates the gate itself; only the observer must be supplied.

Solutions

  1. Pass the actual observer instance you intend to wrap
  2. Check why the observer is null upstream (e.g. SubscribeSafeAsync was called with null) and fix that call site
  3. Guard with a null check before calling Synchronize

Example fix

// before
var wrapped = AsyncObserver.Synchronize(observer); // observer null
// after
if (observer == null) throw new ArgumentNullException(nameof(observer));
var wrapped = AsyncObserver.Synchronize(observer);
Defensive patterns

Strategy: validation

Validate before calling

if (observer is null) throw new ArgumentNullException(nameof(observer));
var wrapped = AsyncObserver.Synchronize(observer);

Type guard

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

Try / catch

try { var wrapped = AsyncObserver.Synchronize(observer); }
catch (ArgumentNullException ex) when (ex.ParamName == "observer") { /* log and use original pipeline */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.Synchronize<TSource>(null), typically from custom operator code that forwards an observer received as null or from a variable that was never assigned.

Common situations: Writing a custom IAsyncObservable whose Subscribe receives a null observer, or composing observers where an earlier factory call returned null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Synchronize.cs:38

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

            return CreateAsyncObservable<TSource>.From(
                source,
                gate,
                static (source, gate, observer) => source.SubscribeSafeAsync(AsyncObserver.Synchronize(observer, gate)));
        }
    }

    public partial class AsyncObserver
    {
        public static IAsyncObserver<TSource> Synchronize<TSource>(IAsyncObserver<TSource> observer)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return Synchronize(observer, new AsyncGate());
        }

        public static IAsyncObserver<TSource> Synchronize<TSource>(IAsyncObserver<TSource> observer, AsyncGate gate)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (gate == null)
                throw new ArgumentNullException(nameof(gate));

            return Create<TSource>(
                async x =>
                {
                    using (await gate.LockAsync().ConfigureAwait(false))
                    {
                        await observer.OnNextAsync(x).ConfigureAwait(false);
                    }

View on GitHub (pinned to 94b5d5ab91)