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
- Check the value passed to RefCount is a non-null IConnectableAsyncObservable<TSource> before calling it
- Trace the producer of the source (e.g. Publish/AsyncPublish call) and fix why it returned null
- Guard the call site with a null check or throw a descriptive exception upstream
- 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
- Never build RefCount chains from nullable variables; assert non-null right after Publish
- Enable nullable reference types (C# 8+) so null flow is caught at compile time
- Keep Publish/RefCount pairs in the same method scope to avoid null handoff
- Unit-test subscription chains with construction-time argument validation
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
- ArgumentNullException
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'repeatCount')
- source
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)