dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'onCompleted')

Error message

Value cannot be null. (Parameter 'onCompleted')

What it means

Observer.Create<T>(onNext, onCompleted) throws ArgumentNullException when the onCompleted delegate is null. AnonymousObserver stores both delegates and invokes onCompleted when the sequence terminates, so a null would surface as an NRE inside the library; the public factory rejects it up front.

Solutions

  1. Supply an onCompleted delegate, e.g. () => { }, if completion handling is not needed.
  2. Pass null-safe wrappers built from possibly-null handlers before calling Create.
  3. Prefer Observer.Create<T>(onNext) (single-argument overload) when only onNext matters.

Example fix

// before
var obs = Observer.Create<int>(x => Handle(x), null);
// after
var obs = Observer.Create<int>(x => Handle(x), () => { });
Defensive patterns

Strategy: validation

Validate before calling

if (onCompleted == null) throw new ArgumentNullException(nameof(onCompleted));
var obs = Observer.Create<int>(onNext, onCompleted);

Type guard

static bool HasOnCompleted(Action onCompleted) => onCompleted is not null;

Try / catch

try { var obs = Observer.Create<int>(onNext, onCompleted); }
catch (ArgumentNullException ex) when (ex.ParamName == "onCompleted") { /* use single-arg overload */ }

Prevention

When it happens

Trigger: Calling Observer.Create<T>(onNext, null) — a null Action for the onCompleted parameter. Checked at Observer.Extensions.cs:111 after the onNext validation.

Common situations: Omitting the completion handler because the sequence is treated as infinite; forgetting to wire the completion callback when generating delegates dynamically; copy-pasting the single-delegate Create overload's signature incorrectly.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Observer.Extensions.cs:111

        /// <summary>
        /// Creates an observer from the specified OnNext and OnCompleted actions.
        /// </summary>
        /// <typeparam name="T">The type of the elements received by the observer.</typeparam>
        /// <param name="onNext">Observer's OnNext action implementation.</param>
        /// <param name="onCompleted">Observer's OnCompleted action implementation.</param>
        /// <returns>The observer object implemented using the given actions.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="onNext"/> or <paramref name="onCompleted"/> is null.</exception>
        public static IObserver<T> Create<T>(Action<T> onNext, Action onCompleted)
        {
            if (onNext == null)
            {
                throw new ArgumentNullException(nameof(onNext));
            }

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

            return new AnonymousObserver<T>(onNext, onCompleted);
        }

        /// <summary>
        /// Creates an observer from the specified OnNext, OnError, and OnCompleted actions.
        /// </summary>
        /// <typeparam name="T">The type of the elements received by the observer.</typeparam>
        /// <param name="onNext">Observer's OnNext action implementation.</param>
        /// <param name="onError">Observer's OnError action implementation.</param>
        /// <param name="onCompleted">Observer's OnCompleted action implementation.</param>
        /// <returns>The observer object implemented using the given actions.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="onNext"/> or <paramref name="onError"/> or <paramref name="onCompleted"/> is null.</exception>
        public static IObserver<T> Create<T>(Action<T> onNext, Action<Exception> onError, Action onCompleted)
        {
            if (onNext == null)
            {

View on GitHub (pinned to 94b5d5ab91)