dotnet/reactive · error · ArgumentNullException
sources
Error message
sources
What it means
The Case(selector, sources, defaultSource) overload throws ArgumentNullException when the sources dictionary is null. The dictionary defines the branch mapping from selector values to observables, so a null map is invalid and rejected at Observable.Imperative.cs:140 before delegation.
Solutions
- Construct and pass a populated IDictionary<TValue, IObservable<TResult>> (it may be empty if you always want defaultSource).
- Guard the producing method so it returns an empty dictionary rather than null.
- Initialize the dictionary before wiring the Case operator.
Example fix
// before IDictionary<string, IObservable<int>> routes = LoadRoutes(); // may be null Observable.Case(GetKey, routes, fallback); // after IDictionary<string, IObservable<int>> routes = LoadRoutes() ?? new Dictionary<string, IObservable<int>>(); Observable.Case(GetKey, routes, fallback);
Defensive patterns
Strategy: validation
Validate before calling
if (sources is null) throw new ArgumentNullException(nameof(sources)); var result = Observable.Case(selector, sources, defaultSource);
Try / catch
try { var q = Observable.Case(selector, sources, defaultSource); }
catch (ArgumentNullException ex) when (ex.ParamName == "sources") { /* fall back to a defaultSource-only observable */ } Prevention
- Use non-nullable dictionary fields with initializers so they are always constructed.
- Make loader methods return empty dictionaries rather than null.
- Validate branch-table construction at startup, not at operator call time.
When it happens
Trigger: Calling Observable.Case with null in the second parameter (IDictionary<TValue, IObservable<TResult>>), e.g. a dictionary built lazily or loaded from config that was never populated/created.
Common situations: Conditional initialization where the branch table is only built in one environment; a lookup helper returning null on miss; deserialization of route tables that produced null.
Related errors
- selector
- defaultSource
- Value cannot be null. (Parameter 'source')
- scheduler
- Value cannot be null. (Parameter 'onErrorAsync')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/3687c2f909baada9.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Imperative.cs:140
/// </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="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>View on GitHub (pinned to 94b5d5ab91)