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

  1. Pass Empty<TResult>(scheduler) as defaultSource when no default behavior is wanted.
  2. Provide a real fallback observable that emits an error or completed signal.
  3. 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

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


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)