dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'disposables')

Error message

Value cannot be null. (Parameter 'disposables')

What it means

The params-array overload StableCompositeAsyncDisposable.Create(params IAsyncDisposable[] disposables) rejects a null array via ArgumentNullException. The library validates inputs at creation so DisposeAsync later never sees a null set.

Solutions

  1. Pass a non-null array (use Array.Empty<IAsyncDisposable>() if there are none).
  2. Fix the source of the array so it never returns null.
  3. If items themselves may be null, filter them: disposables.Where(d => d != null).ToArray().

Example fix

// before
var arr = GetDisposables(); // may return null
var composite = StableCompositeAsyncDisposable.Create(arr);
// after
var arr = GetDisposables() ?? Array.Empty<IAsyncDisposable>();
var composite = StableCompositeAsyncDisposable.Create(arr);
Defensive patterns

Strategy: validation

Validate before calling

if (disposables is null) disposables = Array.Empty<IAsyncDisposable>();
var composite = StableCompositeAsyncDisposable.Create(disposables);

Type guard

static bool IsDisposableArray(IAsyncDisposable[]? a) => a is not null;

Try / catch

try { var c = StableCompositeAsyncDisposable.Create(arr); }
catch (ArgumentNullException ex) when (ex.ParamName == "disposables")
{ arr = Array.Empty<IAsyncDisposable>(); }

Prevention

When it happens

Trigger: Calling Create((IAsyncDisposable[])null) — usually when a null array variable or a method returning null is passed to the params overload.

Common situations: Passing an array from configuration or another method that returned null; explicit cast to disambiguate overloads hitting the array overload with null; refactors renaming the array variable.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Disposables/StableCompositeAsyncDisposable.cs:26

namespace System.Reactive.Disposables
{
    public abstract class StableCompositeAsyncDisposable : IAsyncDisposable
    {
        public static StableCompositeAsyncDisposable Create(IAsyncDisposable disposable1, IAsyncDisposable disposable2)
        {
            if (disposable1 == null)
                throw new ArgumentNullException(nameof(disposable1));
            if (disposable2 == null)
                throw new ArgumentNullException(nameof(disposable2));

            return new Binary(disposable1, disposable2);
        }

        public static StableCompositeAsyncDisposable Create(params IAsyncDisposable[] disposables)
        {
            if (disposables == null)
                throw new ArgumentNullException(nameof(disposables));

            return new NAry(disposables);
        }

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

            return new NAry(disposables);
        }

        public abstract ValueTask DisposeAsync();

        private sealed class Binary : StableCompositeAsyncDisposable
        {
            private volatile IAsyncDisposable _disposable1;
            private volatile IAsyncDisposable _disposable2;

View on GitHub (pinned to 94b5d5ab91)