dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'disposable')

Error message

Value cannot be null. (Parameter 'disposable')

What it means

CompositeAsyncDisposable.AddAsync registers an IAsyncDisposable to be disposed when the composite is disposed. A null argument is rejected immediately with ArgumentNullException naming 'disposable', because the composite would otherwise throw during DisposeAsync when iterating its children.

Solutions

  1. Ensure a non-null IAsyncDisposable is produced before calling AddAsync
  2. Skip the AddAsync call when the value is null
  3. Substitute AsyncDisposable.Nop for a null disposable

Example fix

// before
var d = CreateResource(); // may return null
await composite.AddAsync(d);
// after
var d = CreateResource();
if (d != null)
    await composite.AddAsync(d);
Defensive patterns

Strategy: type-guard

Validate before calling

if (disposable != null) await composite.AddAsync(disposable);

Type guard

bool IsAddable(IAsyncDisposable? disposable) => disposable is not null;

Try / catch

try { await composite.AddAsync(disposable); } catch (ArgumentNullException ex) when (ex.ParamName == "disposable") { await composite.AddAsync(AsyncDisposable.Nop); }

Prevention

When it happens

Trigger: await composite.AddAsync(null) — typically a factory/method that returned null instead of a disposable, or a nullable field not yet initialized.

Common situations: Conditional resource creation that skips assignment; passing the result of a TryGet-style API that yields null; refactoring where a disposable was removed but call sites still add it.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Disposables/CompositeAsyncDisposable.cs:42

        {
            if (disposables == null)
                throw new ArgumentNullException(nameof(disposables));

            _disposables = new List<IAsyncDisposable>(disposables);
        }

        public CompositeAsyncDisposable(IEnumerable<IAsyncDisposable> disposables)
        {
            if (disposables == null)
                throw new ArgumentNullException(nameof(disposables));

            _disposables = new List<IAsyncDisposable>(disposables);
        }

        public async ValueTask AddAsync(IAsyncDisposable disposable)
        {
            if (disposable == null)
                throw new ArgumentNullException(nameof(disposable));

            var shouldDispose = false;

            using (await _gate.LockAsync().ConfigureAwait(false))
            {
                if (_disposed)
                {
                    shouldDispose = true;
                }
                else
                {
                    _disposables.Add(disposable);
                }
            }

            if (shouldDispose)
            {
                await disposable.DisposeAsync().ConfigureAwait(false);

View on GitHub (pinned to 94b5d5ab91)