dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'defaultSource')
Error message
Value cannot be null. (Parameter 'defaultSource')
What it means
Thrown by Case<TValue, TResult>(selector, sources, defaultSource) when the defaultSource observable is null. This source is subscribed when the selector's value has no entry in the sources dictionary; the operator requires an explicit non-null default, so null is rejected when the operator is created.
Solutions
- Pass Empty<TResult>(scheduler) as defaultSource when no default behavior is wanted.
- Provide a real fallback observable that emits an error or completed signal.
- If you don't need a default, use the Case(selector, sources, scheduler) overload.
Example fix
// before var stream = Case(selector, sources, null); // meant "no default" // after var stream = Case(selector, sources, Empty<TResult>(TaskPoolAsyncScheduler.Default));
Defensive patterns
Strategy: validation
Validate before calling
if (defaultSource is null) defaultSource = Empty<TResult>(TaskPoolAsyncScheduler.Default);
Type guard
bool HasDefault<TResult>(IAsyncObservable<TResult>? o) => o is not null;
Try / catch
try { var s = Case(selector, sources, defaultSource); }
catch (ArgumentNullException ex) when (ex.ParamName == "defaultSource") { /* use Empty<TResult>() */ } Prevention
- Use Empty<TResult>(scheduler) rather than null to mean 'no default'
- Provide an explicit fallback observable (complete or OnError) for unmatched keys
- Prefer the Case(selector, sources, scheduler) overload when no default is needed
When it happens
Trigger: Calling Case(selector, sources, defaultSource) with defaultSource == null, e.g. passing null intending 'no default', or Empty<TResult>(scheduler) result stored in a nullable that evaluated to null.
Common situations: Users expecting a null default to mean 'do nothing' — use Empty<TResult>(scheduler) instead; DI/config failing to provide the default stream; wrong overload chosen (scheduler overload expects IAsyncScheduler, not null observable).
Related errors
- Value cannot be null. (Parameter 'selector')
- Value cannot be null. (Parameter 'sources')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'error')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/d74d2cc1fec50e45.
Report an issue: GitHub.
Appendix: source
Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/Case.cs:24
using System.Reactive.Concurrency;
using System.Threading.Tasks;
namespace System.Reactive.Linq
{
public partial class AsyncObservable
{
public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources) => Case(selector, sources, Empty<TResult>());
public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncScheduler scheduler) => Case(selector, sources, Empty<TResult>(scheduler));
public static IAsyncObservable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IAsyncObservable<TResult>> sources, IAsyncObservable<TResult> defaultSource)
{
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 Create<TResult>(observer =>
{
var source = default(IAsyncObservable<TResult>);
try
{
var value = selector();
if (!sources.TryGetValue(value, out source))
{
source = defaultSource;
}
}
catch (Exception ex)
{
return Throw<TResult>(ex).SubscribeAsync(observer);
}View on GitHub (pinned to 94b5d5ab91)