dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source16')

Error message

Value cannot be null. (Parameter 'source16')

What it means

ArgumentNullException (Parameter 'source16'): the 16th and final observable source of the 16-ary Observable.Zip overload is null. The operator validates all sources first (then resultSelector), throwing ArgumentNullException naming the null parameter before any subscription occurs.

Solutions

  1. Provide a non-null IObservable<T> for the 16th argument.
  2. Substitute Observable.Empty<T>() / Observable.Never<T>() when the final stream is intentionally absent.
  3. Null-check all sources together before invoking Zip.
  4. Reconsider arity: use the IEnumerable overload when sources are dynamic.

Example fix

// before
Zip(..., s15, s16 /* null */, sel);
// after
Zip(..., s15, s16 ?? Observable.Empty<int>(), sel);
Defensive patterns

Strategy: validation

Validate before calling

if (source16 == null) throw new ArgumentNullException(nameof(source16));
// or:
var s16 = source16 ?? Observable.Empty<T16>();

Type guard

static IObservable<T> Coalesce<T>(IObservable<T>? o) => o ?? Observable.Empty<T>();
var s16 = Coalesce(source16);

Try / catch

try
{
    var zipped = Observable.Zip(source1, /* ... */ source16, selector);
}
catch (ArgumentNullException ex) when (ex.ParamName == nameof(source16))
{
    logger.LogError(ex, "source16 was null when composing Zip");
}

Prevention

When it happens

Trigger: Observable.Zip(source1..source16, resultSelector) called with source16 == null, typically the last-added source after expanding a smaller zip, or a trailing optional stream left null.

Common situations: Growing a zip from 15 to 16 sources and forgetting the new argument, default parameter values of null, or template-generated source lists with a trailing empty slot.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Linq/Observable.Multiple.Zip.cs:1169

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

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

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

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

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

            return s_impl.Zip(source1, source2, source3, source4, source5, source6, source7, source8, source9, source10, source11, source12, source13, source14, source15, source16, resultSelector);
        }

    }

#pragma warning disable CA1711 // (Don't use Ex suffix.) This has been a public type for many years, so we can't rename it now.
    public static partial class ObservableEx
#pragma warning restore CA1711
    {
        /// <summary>
        /// Merges the specified observable sequences into one observable sequence of tuple values whenever all of the observable sequences have produced an element at a corresponding index.

View on GitHub (pinned to 94b5d5ab91)