dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

ArgumentNullException thrown by Synchronization.SubscribeOn<TSource>(IObservable<TSource>, IScheduler) when the source sequence is null. SubscribeOn wraps the source in a SubscribeOnObservable so the Subscribe call itself runs on the given scheduler; the source must exist for that wrapper to delegate to.

Solutions

  1. Ensure the IObservable<TSource> passed to SubscribeOn is non-null; replace null-returning producers with Observable.Empty<TSource>() or Observable.Never<TSource>().
  2. Null-check the source before calling SubscribeOn and handle the null case (log, throw a domain error, or use a fallback sequence).
  3. Fix the upstream factory or DI registration so the observable is always produced instead of returning null.
  4. Guard at the call site so a null source fails fast with your own descriptive exception if that is the intended contract.

Example fix

// before
IObservable<int> source = _repository.GetData(); // may return null
var scheduled = source.SubscribeOn(Scheduler.ThreadPool);
// after
IObservable<int> source = _repository.GetData() ?? Observable.Empty<int>();
var scheduled = source.SubscribeOn(Scheduler.ThreadPool);
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) throw new InvalidOperationException("Source observable must not be null before SubscribeOn");
var scheduled = source.SubscribeOn(Scheduler.ThreadPool);

Type guard

bool IsUsableSource<TSource>(IObservable<TSource> source) => source is not null;

Try / catch

try
{
    var scheduled = source.SubscribeOn(Scheduler.ThreadPool);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    scheduled = Observable.Empty<TSource>().SubscribeOn(Scheduler.ThreadPool);
}

Prevention

When it happens

Trigger: Calling source.SubscribeOn(scheduler) where the source expression evaluates to null — commonly a nullable field or property holding the observable, or a method that returned null instead of an empty or never sequence.

Common situations: Chaining off a repository or service method whose observable result is null on error paths; DI-resolved observables that failed to bind; legacy code returning null instead of Observable.Empty or Observable.Never.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Concurrency/Synchronization.cs:35

        #region SubscribeOn

        /// <summary>
        /// Wraps the source sequence in order to run its subscription and unsubscription logic on the specified scheduler.
        /// </summary>
        /// <typeparam name="TSource">The type of the elements in the source sequence.</typeparam>
        /// <param name="source">Source sequence.</param>
        /// <param name="scheduler">Scheduler to perform subscription and unsubscription actions on.</param>
        /// <returns>The source sequence whose subscriptions and unsubscriptions happen on the specified scheduler.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="source"/> or <paramref name="scheduler"/> is <c>null</c>.</exception>
        /// <remarks>
        /// Only the side-effects of subscribing to the source sequence and disposing subscriptions to the source sequence are run on the specified scheduler.
        /// In order to invoke observer callbacks on the specified scheduler, e.g. to offload callback processing to a dedicated thread, use <see cref="Synchronization.ObserveOn{TSource}(IObservable{TSource}, IScheduler)"/>.
        /// </remarks>
        public static IObservable<TSource> SubscribeOn<TSource>(IObservable<TSource> source, IScheduler scheduler)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

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

            return new SubscribeOnObservable<TSource>(source, scheduler);
        }

        private sealed class SubscribeOnObservable<TSource> : ObservableBase<TSource>
        {
            private sealed class Subscription : IDisposable
            {
                private SerialDisposableValue _cancel;

                public Subscription(IObservable<TSource> source, IScheduler scheduler, IObserver<TSource> observer)
                {

View on GitHub (pinned to 94b5d5ab91)