dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'source')

Error message

Value cannot be null. (Parameter 'source')

What it means

RefCount wraps an IConnectableAsyncObservable so it connects when the first observer subscribes and disconnects when the last unsubscribes. This guard clause throws ArgumentNullException immediately when the source connectable observable is null, because RefCount cannot operate without a source to attach to.

Solutions

  1. Check the value passed to RefCount is a non-null IConnectableAsyncObservable<TSource> before calling it
  2. Trace the producer of the source (e.g. Publish/AsyncPublish call) and fix why it returned null
  3. Guard the call site with a null check or throw a descriptive exception upstream
  4. Verify the source variable is initialized before the subscription chain is built

Example fix

// before
IConnectableAsyncObservable<int> conn = maybePublish();
var obs = conn.RefCount(); // throws if maybePublish() returned null
// after
IConnectableAsyncObservable<int> conn = maybePublish() ?? throw new InvalidOperationException("Publish returned null source");
var obs = conn.RefCount();
Defensive patterns

Strategy: validation

Validate before calling

if (source == null) throw new InvalidOperationException("RefCount requires a non-null IConnectableAsyncObservable; check the upstream Publish call.");
var refCounted = AsyncObservable.RefCount(source);

Type guard

static bool IsConnectable<TSource>(object o) => o is IConnectableAsyncObservable<TSource> conn && conn != null;

Try / catch

try
{
    var refCounted = AsyncObservable.RefCount(connectable);
}
catch (ArgumentNullException ex) when (ex.ParamName == "source")
{
    // log and fall back to a default connectable source
    connectable = upstream.AsyncPublish();
    var refCounted = AsyncObservable.RefCount(connectable);
}

Prevention

When it happens

Trigger: Calling AsyncObservable.Recount source) or any method chain whose upstream operator returned null (e.g. a factory method or cached variable that was never assigned) instead of a real IConnectableAsyncObservable<TSource>.

Common situations: A Publish/RefCount chain where Publish was called on a variable that is null; DI or configuration produced no connectable source; refactoring removed an assignment so the connectable flows as null.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Linq/Operators/RefCount.cs:16

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information. 

using System.Reactive.Disposables;
using System.Reactive.Subjects;
using System.Threading;

namespace System.Reactive.Linq
{
    public partial class AsyncObservable
    {
        public static IAsyncObservable<TSource> RefCount<TSource>(this IConnectableAsyncObservable<TSource> source)
        {
            if (source == null)
                throw new ArgumentNullException(nameof(source));

            var gate = new AsyncGate();
            var count = 0;
            var connectable = default(IAsyncDisposable);

            return Create<TSource>(async observer =>
            {
                var subscription = await source.SubscribeSafeAsync(observer).ConfigureAwait(false);

                using (await gate.LockAsync().ConfigureAwait(false))
                {
                    if (++count == 1)
                    {
                        connectable = await source.ConnectAsync().ConfigureAwait(false);
                    }
                }

                return AsyncDisposable.Create(async () =>

View on GitHub (pinned to 94b5d5ab91)