dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'defaultSource')

Error message

Value cannot be null. (Parameter 'defaultSource')

What it means

The Case operator throws ArgumentNullException with parameter name 'defaultSource' when the fallback sequence used when the selector's value has no dictionary entry is null. Ix.NET validates all arguments eagerly so the failure happens at the call site. Use an empty sequence, not null, to express 'no fallback elements'.

Solutions

  1. Pass Enumerable.Empty<TResult>() instead of null for an empty fallback.
  2. Check the expression producing defaultSource for an early return or failed lookup yielding null.
  3. If null is possible upstream, coalesce: defaultSource ?? Enumerable.Empty<TResult>().
  4. Enable nullable reference type annotations to catch this at compile time.

Example fix

// before
var seq = Case(() => key, sources, null);
// after
var seq = Case(() => key, sources, Enumerable.Empty<int>());
Defensive patterns

Strategy: validation

Validate before calling

if (defaultSource is null)
    throw new ArgumentNullException(nameof(defaultSource));
// or normalize:
defaultSource ??= Enumerable.Empty<TResult>();

Type guard

static bool HasDefault<TResult>(IEnumerable<TResult> def) => def != null;

Try / catch

try
{
    var seq = Case(selector, sources, defaultSource);
}
catch (ArgumentNullException ex) when (ex.ParamName == "defaultSource")
{
    var seq = Case(selector, sources, Enumerable.Empty<TResult>());
}

Prevention

When it happens

Trigger: Calling Case<TValue,TResult>(selector, sources, defaultSource) with null as the third argument (the fallback sequence).

Common situations: A factory or method call returning null as the default source; assuming null means 'nothing' instead of Enumerable.Empty<T>(); legacy code using null sentinels for empty sequences.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Case.cs:49

        /// default sequence.
        /// </summary>
        /// <typeparam name="TValue">Type of the selector value.</typeparam>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="selector">Selector function used to pick a sequence from the given sources.</param>
        /// <param name="sources">Dictionary mapping selector values onto resulting sequences.</param>
        /// <param name="defaultSource">
        /// Default sequence to return in case there's no corresponding source for the computed
        /// selector value.
        /// </param>
        /// <returns>The source sequence corresponding with the evaluated selector value; otherwise, the default source.</returns>
        public static IEnumerable<TResult> Case<TValue, TResult>(Func<TValue> selector, IDictionary<TValue, IEnumerable<TResult>> sources, IEnumerable<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 Defer(() =>
            {
                if (!sources.TryGetValue(selector(), out var result))
                {
                    result = defaultSource;
                }

                return result;
            });
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)