dotnet/reactive · error · ArgumentNullException

Thrown when source is null (ArgumentNullException, param…

Error message

Thrown when source is null (ArgumentNullException, param name: source)

What it means

The Do(source, observer) overload eagerly validates that the source sequence is non-null and throws ArgumentNullException with parameter name 'source' otherwise. The observer form forwards OnNext/OnError/OnCompleted to the given IObserver during enumeration, but the source itself must still be a real sequence.

Solutions

  1. Coalesce with `?? Enumerable.Empty<T>()` before calling Do
  2. Assert/null-check the source at the pipeline boundary
  3. Make the sequence producer return empty collections instead of null
  4. Only attach the Do(observer) stage when the source is known non-null

Example fix

// before
var result = GetSequence().Do(observer);
// after
var result = (GetSequence() ?? Enumerable.Empty<Event>()).Do(observer);
Defensive patterns

Strategy: validation

Validate before calling

if (source is null) source = Enumerable.Empty<TSource>();

Type guard

static IEnumerable<T> NonNull<T>(IEnumerable<T>? s) => s ?? Enumerable.Empty<T>();

Try / catch

try { var result = source!.Do(observer); ... }
catch (ArgumentNullException ex) when (ex.ParamName == "source") { Log("source sequence was null"); }

Prevention

When it happens

Trigger: `null.Do(myObserver)` via extension syntax or Enumerable.Do(null, observer); a nullable source from a lookup or factory piped into the observer-based Do.

Common situations: Bridging IEnumerable pipelines into Rx-style observers where the source comes from a repository that can return null; uninitialized test fixtures; conditional pipeline assembly.

Related errors


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

Appendix: source

Thrown at Ix.NET/Source/System.Interactive/System/Linq/Operators/Do.cs:102

            if (onError == null)
                throw new ArgumentNullException(nameof(onError));
            if (onCompleted == null)
                throw new ArgumentNullException(nameof(onCompleted));

            return DoCore(source, onNext, onError, onCompleted);
        }

        /// <summary>
        /// Lazily invokes observer methods for each value in the sequence, and upon successful or exceptional termination.
        /// </summary>
        /// <typeparam name="TSource">Source sequence element type.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="observer">Observer to invoke notification calls on.</param>
        /// <returns>Sequence exhibiting the side-effects of observer method invocation upon enumeration.</returns>
        public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));
            if (observer == null)
                throw new ArgumentNullException(nameof(observer));

            return DoCore(source, observer.OnNext, observer.OnError, observer.OnCompleted);
        }

        private static IEnumerable<TSource> DoCore<TSource>(IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
        {
            using var e = source.GetEnumerator();

            while (true)
            {
                TSource current;
                try
                {
                    if (!e.MoveNext())
                        break;

View on GitHub (pinned to 94b5d5ab91)