dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

Publish(source) throws ArgumentNullException when the source sequence is null. Publish buffers the sequence for multicasting, and it needs a real enumerator, so the argument is validated eagerly before creating the PublishedBuffer.

Solutions

  1. Ensure the source is non-null before publishing; substitute Enumerable.Empty<TSource>().
  2. Coalesce at the call: (source ?? Enumerable.Empty<T>()).Publish().
  3. Fix the code path that produced a null sequence.

Example fix

// before
var buffer = source.Publish(); // source may be null
// after
var buffer = (source ?? Enumerable.Empty<int>()).Publish();
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) source = Enumerable.Empty<int>();
var buffer = source.Publish();

Type guard

static bool CanPublish(IEnumerable<int>? source) => source is not null;

Try / catch

try
{
    using var buffer = source.Publish();
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    // handle missing source
}

Prevention

When it happens

Trigger: Calling source.Publish() where source is a null IEnumerable<TSource>.

Common situations: Passing a nullable sequence obtained from parsing, deserialization, or an optional collection property straight into Publish.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Publish.cs:38

        /// at the point of obtaining the enumerator.
        /// </returns>
        /// <example>
        /// var rng = Enumerable.Range(0, 10).Publish();
        /// var e1 = rng.GetEnumerator();    // e1 has a view on the source starting from element 0
        /// Assert.IsTrue(e1.MoveNext());
        /// Assert.AreEqual(0, e1.Current);
        /// Assert.IsTrue(e1.MoveNext());
        /// Assert.AreEqual(1, e1.Current);
        /// var e2 = rng.GetEnumerator();
        /// Assert.IsTrue(e2.MoveNext());    // e2 has a view on the source starting from element 2
        /// Assert.AreEqual(2, e2.Current);
        /// Assert.IsTrue(e1.MoveNext());    // e1 continues to enumerate over its view
        /// Assert.AreEqual(2, e1.Current);
        /// </example>
        public static IBuffer<TSource> Publish<TSource>(this IEnumerable<TSource> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            return new PublishedBuffer<TSource>(source.GetEnumerator());
        }

        /// <summary>
        /// Publishes the source sequence within a selector function where each enumerator can obtain a view over a tail of the
        /// source sequence.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <typeparam name="TResult">Result sequence element type.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="selector">Selector function with published access to the source sequence for each enumerator.</param>
        /// <returns>Sequence resulting from applying the selector function to the published view over the source sequence.</returns>
        public static IEnumerable<TResult> Publish<TSource, TResult>(this IEnumerable<TSource> source, Func<IEnumerable<TSource>, IEnumerable<TResult>> selector)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (selector == null)

View on GitHub (pinned to 94b5d5ab91)