dotnet/reactive · error · ArgumentNullException

nameof(predicate)

Error message

nameof(predicate)

What it means

The message is "Value cannot be null. (Parameter 'predicate')" thrown at Observable.Blocking.cs:540: SingleOrDefault with a filter predicate requires a non-null Func<TSource,bool>, and it is validated immediately after the source check. The predicate is applied synchronously to each element while blocking for the single result, so a null predicate has no defined behavior and the operator rejects it up front.

Solutions

  1. Ensure a concrete predicate is supplied: obs.SingleOrDefault(x => x.Id == id);
  2. If filtering is optional, branch: apply the predicate overload only when a predicate exists, otherwise call the parameterless SingleOrDefault overload (line 513).
  3. Null-check the delegate before calling, and fix whatever produced the null predicate (config binding, factory, DI registration).

Example fix

// before
Func<Order, bool> filter = GetFilter(); // may return null
var order = orders.SingleOrDefault(filter); // ArgumentNullException('predicate')
// after
var order = filter != null
    ? orders.SingleOrDefault(filter)
    : orders.SingleOrDefault();
Defensive patterns

Strategy: validation

Validate before calling

if (predicate is null)
{
    value = source.SingleOrDefault(); // optional-filter path
}
else
{
    value = source.SingleOrDefault(predicate);
}

Type guard

bool HasFilter<T>(Func<T, bool>? predicate) => predicate is not null;

Try / catch

try
{
    var value = source.SingleOrDefault(pred);
}
catch (ArgumentNullException ex) when (ex.ParamName == "predicate")
{
    // predicate was null; fall back to unfiltered single element
    value = source.SingleOrDefault();
}

Prevention

When it happens

Trigger: Calling Observable.SingleOrDefault<TSource>(source, null) with a null predicate — commonly because the predicate was built conditionally, came from an uninitialized delegate field, or was received as a null method-group/lambda result from another API.

Common situations: Conditional filtering logic where the predicate variable is only assigned on one branch; a strategy/predicate injected via configuration or DI that resolved to null; copying an async LINQ pattern where the predicate is optional and passing null 'to skip' it.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Blocking.cs:540

        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source observable sequence.</param>
        /// <param name="predicate">A predicate function to evaluate for elements in the source sequence.</param>
        /// <returns>The single element in the observable sequence that satisfies the condition in the predicate, or a default value if no such element exists.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="predicate"/> is null.</exception>
        /// <exception cref="InvalidOperationException">The sequence contains more than one element that satisfies the condition in the predicate.</exception>
        /// <seealso cref="Observable.SingleOrDefaultAsync{TSource}(IObservable{TSource}, Func{TSource, bool})"/>
        [Obsolete(Constants_Linq.UseAsync)]
        [return: MaybeNull]
        public static TSource SingleOrDefault<TSource>(this IObservable<TSource> source, Func<TSource, bool> predicate)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            return s_impl.SingleOrDefault(source, predicate);
        }

        #endregion

        #region + Wait +

        /// <summary>
        /// Waits for the observable sequence to complete and returns the last element of the sequence.
        /// If the sequence terminates with an OnError notification, the exception is thrown.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source observable sequence.</param>
        /// <returns>The last element in the observable sequence.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> is null.</exception>
        /// <exception cref="InvalidOperationException">The source sequence is empty.</exception>

View on GitHub (pinned to 94b5d5ab91)