dotnet/reactive · error · ArgumentNullException

Argument cannot be null (Parameter name: predicate)

Error message

Argument cannot be null (Parameter name: predicate)

What it means

AsyncObserver.First (the observer-level overload taking a sync predicate) throws ArgumentNullException when the predicate delegate is null. The AsyncRx operators validate all delegate arguments up front because a null predicate would only explode later, mid-stream, when the first element arrives. Failing fast at operator-construction time keeps the error at the call site where it can be fixed.

Solutions

  1. Pass a real predicate; for 'no filtering' semantics call the First overload without a predicate instead of passing null.
  2. If the predicate is computed, default it before the call: predicate ?? (_ => true) only when filtering is intentionally bypassed.
  3. Check the caller (FirstAsync) at First.cs and ensure the value forwarded is a non-null delegate; guard at your own boundary with ArgumentNullException.ThrowIfNull(predicate).

Example fix

// before
Func<int, bool> pred = condition ? x => x > 0 : null;
var obs = AsyncObserver.First(observer, pred);

// after
var obs = condition ? AsyncObserver.First(observer, (int x) => x > 0) : AsyncObserver.First(observer);
Defensive patterns

Strategy: validation

Validate before calling

if (predicate is null) throw new ArgumentNullException(nameof(predicate));
var obs = AsyncObserver.First(observer, predicate);

Type guard

static bool IsValid<T>(Func<T, bool>? p) => p is not null;

Try / catch

try { var obs = AsyncObserver.First(observer, predicate); }
catch (ArgumentNullException ex) when (ex.ParamName == "predicate") { /* supply default predicate or log */ }

Prevention

When it happens

Trigger: Calling AsyncObserver.First(observer, predicate) (Func<TSource, bool> overload) with a null predicate, typically via FirstAsync(source, (Func<TSource,bool>)null) or by passing a nullable delegate variable that was never assigned.

Common situations: Conditional predicate construction (build predicate only if a filter flag is set) that leaves the variable null; casting/reflective invocation passing null for the optional filter; refactoring where a lambda was moved out and the variable lost its initializer.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/First.cs:76

                async x =>
                {
                    await observer.OnNextAsync(x).ConfigureAwait(false);
                    await observer.OnCompletedAsync().ConfigureAwait(false);
                },
                observer.OnErrorAsync,
                async () =>
                {
                    await observer.OnErrorAsync(new InvalidOperationException("The sequence is empty.")).ConfigureAwait(false);
                }
            );
        }

        public static IAsyncObserver<TSource> First<TSource>(IAsyncObserver<TSource> observer, Func<TSource, bool> predicate)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (predicate == null)
                throw new ArgumentNullException(nameof(predicate));

            return Where(First(observer), predicate);
        }

        public static IAsyncObserver<TSource> First<TSource>(IAsyncObserver<TSource> observer, Func<TSource, ValueTask<bool>> predicate)
        {
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));
            if (predicate == null)
                throw new ArgumentNullException(nameof(predicate));

            return Where(First(observer), predicate);
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)