dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'selector')

Error message

Value cannot be null. (Parameter 'selector')

What it means

Publish(source, selector) throws ArgumentNullException when the selector function is null. The selector is invoked lazily inside the query, so the library rejects a null selector up front to fail fast at the call site.

Solutions

  1. Pass a valid Func<IEnumerable<TSource>, IEnumerable<TResult>>; if no projection is needed, use the parameterless Publish(source) overload.
  2. Coalesce to an identity selector: selector ?? (Func<IEnumerable<int>, IEnumerable<int>>)(s => s).
  3. Fix the code path that left the delegate null.

Example fix

// before
var result = source.Publish(selector); // selector may be null
// after
var result = source.Publish(selector ?? (s => s));
Defensive patterns

Strategy: validation

Validate before calling

if (selector == null) selector = s => s; // identity
var result = source.Publish(selector);

Type guard

static bool HasSelector<TSource, TResult>(Func<IEnumerable<TSource>, IEnumerable<TResult>>? selector) => selector is not null;

Try / catch

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

Prevention

When it happens

Trigger: Calling source.Publish(null) or passing a delegate variable that was never assigned.

Common situations: Storing the selector in a field/property or receiving it as an optional parameter that arrived null; conditional lambda construction that fell through to null.

Related errors


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

Appendix: source

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

            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)
                throw new ArgumentNullException(nameof(selector));

            return Create(() => selector(source.Publish()).GetEnumerator());
        }

        private sealed class PublishedBuffer<T> : IBuffer<T>
        {
            private readonly object _gate = new();
            private readonly RefCountList<T> _buffer;
            private readonly IEnumerator<T> _source;

            private bool _disposed;
            private Exception? _error;
            private bool _stopped;

            public PublishedBuffer(IEnumerator<T> source)
            {
                _buffer = new RefCountList<T>(0);
                _source = source;

View on GitHub (pinned to 94b5d5ab91)