dotnet/reactive · error · ArgumentNullException

defaultSource

Error message

defaultSource

What it means

The Case(selector, sources, defaultSource) overload throws ArgumentNullException when defaultSource is null. This overload uses the default observable when the selector's value is absent from the dictionary, so a null default defeats the operator's contract and is rejected at Observable.Imperative.cs:145.

Solutions

  1. Pass a real fallback observable, e.g. Observable.Empty<TResult>() if doing nothing is the desired default.
  2. Use Observable.Throw<TResult>(...) to make the missing branch an explicit error instead of null.
  3. If no fallback is needed, use the two-argument Case(selector, sources) overload.

Example fix

// before
Observable.Case(selector, sources, GetFallback()); // GetFallback() returns null when unset
// after
Observable.Case(selector, sources, GetFallback() ?? Observable.Empty<int>());
Defensive patterns

Strategy: validation

Validate before calling

if (defaultSource is null) throw new ArgumentNullException(nameof(defaultSource));
var result = Observable.Case(selector, sources, defaultSource);

Try / catch

try { var q = Observable.Case(selector, sources, defaultSource); }
catch (ArgumentNullException ex) when (ex.ParamName == "defaultSource") { /* use Observable.Empty<TResult>() as fallback */ }

Prevention

When it happens

Trigger: Calling Observable.Case(selector, sources, null) — commonly when a fallback observable expression evaluates to null or the developer assumed defaultSource was optional.

Common situations: Building the fallback via a factory that returns null; omission of the fallback during a refactor from the two-argument Case overload; config-driven fallback creation failing silently.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Imperative.cs:145

        /// <param name="defaultSource">Default source to select in case no matching source in <paramref name="sources"/> is found.</param>
        /// <returns>The observable sequence retrieved from the <paramref name="sources"/> dictionary based on the <paramref name="selector"/> invocation result, or <paramref name="defaultSource"/> if no match is found.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="selector"/> or <paramref name="sources"/> or <paramref name="defaultSource"/> is null.</exception>
        public static IObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IObservable<TResult>> sources, IObservable<TResult> defaultSource)
            where TValue : notnull
        {
            if (selector == null)
            {
                throw new ArgumentNullException(nameof(selector));
            }

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

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

            return s_impl.Case(selector, sources, defaultSource);
        }

        /// <summary>
        /// Uses <paramref name="selector"/> to determine which source in <paramref name="sources"/> to return, choosing an empty sequence on the specified scheduler if no match is found.
        /// </summary>
        /// <typeparam name="TValue">The type of the value returned by the selector function, used to look up the resulting source.</typeparam>
        /// <typeparam name="TResult">The type of the elements in the result sequence.</typeparam>
        /// <param name="selector">Selector function invoked to determine the source to lookup in the <paramref name="sources"/> dictionary.</param>
        /// <param name="sources">Dictionary of sources to select from based on the <paramref name="selector"/> invocation result.</param>
        /// <param name="scheduler">Scheduler to generate an empty sequence on in case no matching source in <paramref name="sources"/> is found.</param>
        /// <returns>The observable sequence retrieved from the <paramref name="sources"/> dictionary based on the <paramref name="selector"/> invocation result, or an empty sequence if no match is found.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="selector"/> or <paramref name="sources"/> or <paramref name="scheduler"/> is null.</exception>
        public static IObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IObservable<TResult>> sources, IScheduler scheduler)
            where TValue : notnull
        {

View on GitHub (pinned to 94b5d5ab91)