dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'disposable')

Error message

Value cannot be null. (Parameter 'disposable')

What it means

ScheduledDisposable's constructor requires a non-null IDisposable resource; the value is stored in a SingleAssignmentDisposable and null is rejected with ArgumentNullException. Both constructor parameters are individually validated, so this fires only when the second argument is null.

Solutions

  1. Ensure the resource to dispose is created before constructing ScheduledDisposable.
  2. Use Disposable.Empty as a non-null placeholder when there is nothing to dispose.
  3. Null-check the resource first and skip creating the ScheduledDisposable if absent.

Example fix

// before
var sd = new ScheduledDisposable(scheduler, AcquireResource()); // may be null
// after
var resource = AcquireResource() ?? Disposable.Empty;
var sd = new ScheduledDisposable(scheduler, resource);
Defensive patterns

Strategy: validation

Validate before calling

if (resource is null) resource = Disposable.Empty;
var sd = new ScheduledDisposable(scheduler, resource);

Type guard

static bool HasResource(IDisposable d) => d is not null;

Try / catch

try { var sd = new ScheduledDisposable(scheduler, resource); }
catch (ArgumentNullException ex) when (ex.ParamName == "disposable") { /* substitute Disposable.Empty and retry */ }

Prevention

When it happens

Trigger: Calling new ScheduledDisposable(scheduler, null) — passing null for the 'disposable' parameter, typically when the wrapped resource comes from a factory or optional lookup that returned null.

Common situations: Wrapping the result of a GetResource()/TryGetValue pattern that can return null, or a conditional resource acquisition where one branch never assigns the disposable.

Related errors


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

Appendix: source

Thrown at Rx.NET/Source/src/System.Reactive/Disposables/ScheduledDisposable.cs:25

namespace System.Reactive.Disposables
{
    /// <summary>
    /// Represents a disposable resource whose disposal invocation will be scheduled on the specified <seealso cref="IScheduler"/>.
    /// </summary>
    public sealed class ScheduledDisposable : ICancelable
    {
        private SingleAssignmentDisposableValue _disposable;

        /// <summary>
        /// Initializes a new instance of the <see cref="ScheduledDisposable"/> class that uses an <see cref="IScheduler"/> on which to dispose the disposable.
        /// </summary>
        /// <param name="scheduler">Scheduler where the disposable resource will be disposed on.</param>
        /// <param name="disposable">Disposable resource to dispose on the given scheduler.</param>
        /// <exception cref="ArgumentNullException"><paramref name="scheduler"/> or <paramref name="disposable"/> is null.</exception>
        public ScheduledDisposable(IScheduler scheduler, IDisposable disposable)
        {
            Scheduler = scheduler ?? throw new ArgumentNullException(nameof(scheduler));
            _disposable.Disposable = disposable ?? throw new ArgumentNullException(nameof(disposable));
        }

        /// <summary>
        /// Gets the scheduler where the disposable resource will be disposed on.
        /// </summary>
        public IScheduler Scheduler { get; }

        /// <summary>
        /// Gets the underlying disposable. After disposal, the result is undefined.
        /// </summary>
        public IDisposable Disposable => _disposable.Disposable ?? Disposables.Disposable.Empty;

        /// <summary>
        /// Gets a value that indicates whether the object is disposed.
        /// </summary>
        public bool IsDisposed => _disposable.IsDisposed;

        /// <summary>

View on GitHub (pinned to 94b5d5ab91)