dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'disposable')
Error message
Value cannot be null. (Parameter 'disposable')
What it means
The RefCountDisposable constructor requires a non-null underlying IDisposable; System.Reactive explicitly guards it with a null check and throws ArgumentNullException. The reference-counting wrapper cannot function without a disposable to ref-count, so a null argument is treated as a programming error rather than silently tolerated.
Solutions
- Ensure the underlying IDisposable is created before constructing the RefCountDisposable.
- Use Disposable.Empty as an explicit non-null placeholder when there is nothing to dispose.
- Guard with a null check and fall back to Disposable.Empty or skip creating the RefCountDisposable entirely.
Example fix
// before var refCount = new RefCountDisposable(GetInner()); // GetInner() may return null // after var inner = GetInner() ?? Disposable.Empty; var refCount = new RefCountDisposable(inner);
Defensive patterns
Strategy: validation
Validate before calling
if (inner is null) throw new InvalidOperationException("Underlying disposable must be created before RefCountDisposable");
var rc = new RefCountDisposable(inner); Type guard
static bool IsUsable(IDisposable d) => d is not null;
Try / catch
try { var rc = new RefCountDisposable(inner); }
catch (ArgumentNullException ex) when (ex.ParamName == "disposable") { /* fall back to Disposable.Empty semantics */ } Prevention
- Never pass factory results that can return null directly into the constructor; coalesce with Disposable.Empty.
- Treat null IDisposable as a bug; enforce non-null via nullable reference types (IDisposable not null?).
- Add unit tests covering resource acquisition failure paths.
When it happens
Trigger: Calling new RefCountDisposable(null) or new RefCountDisposable(null, throwWhenDisposed) — i.e. passing a null IDisposable as the 'disposable' parameter, typically when a lazy/deferred producer of the underlying disposable returned null.
Common situations: Passing the result of a factory method or dictionary lookup that returned null (e.g. GetDisposable() from another container), conditional initialization where the inner disposable was never created, or refactoring that changed the order of assignment to a backing field.
Related errors
- Value cannot be null. (Parameter 'disposable')
- Value cannot be null. (Parameter 'scheduler')
- Value cannot be null. (Parameter 'disposable1')
- Value cannot be null. (Parameter 'disposable2')
- Value cannot be null. (Parameter 'disposables')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/1f319cfd1721883b.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Disposables/RefCountDisposable.cs:42
/// <summary>
/// Initializes a new instance of the <see cref="RefCountDisposable"/> class with the specified disposable.
/// </summary>
/// <param name="disposable">Underlying disposable.</param>
/// <exception cref="ArgumentNullException"><paramref name="disposable"/> is null.</exception>
public RefCountDisposable(IDisposable disposable) : this(disposable, false)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RefCountDisposable"/> class with the specified disposable.
/// </summary>
/// <param name="disposable">Underlying disposable.</param>
/// <param name="throwWhenDisposed">Indicates whether subsequent calls to <see cref="GetDisposable"/> should throw when this instance is disposed.</param>
/// <exception cref="ArgumentNullException"><paramref name="disposable"/> is null.</exception>
public RefCountDisposable(IDisposable disposable, bool throwWhenDisposed)
{
_disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
_count = 0;
_throwWhenDisposed = throwWhenDisposed;
}
/// <summary>
/// Gets a value that indicates whether the object is disposed.
/// </summary>
public bool IsDisposed => Volatile.Read(ref _count) == int.MinValue;
/// <summary>
/// Returns a dependent disposable that when disposed decreases the refcount on the underlying disposable.
/// </summary>
/// <returns>A dependent disposable contributing to the reference count that manages the underlying disposable's lifetime.</returns>
/// <exception cref="ObjectDisposedException">This instance has been disposed and is configured to throw in this case by <see cref="RefCountDisposable(IDisposable, bool)"/>.</exception>
public IDisposable GetDisposable()
{
// the current state
var cnt = Volatile.Read(ref _count);View on GitHub (pinned to 94b5d5ab91)