dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'disposable2')

Error message

Value cannot be null. (Parameter 'disposable2')

What it means

StableCompositeAsyncDisposable.Create(disposable1, disposable2) validates both arguments before constructing a Binary composite. The second IAsyncDisposable was null, so the library throws ArgumentNullException immediately rather than failing at disposal time.

Solutions

  1. Pass a non-null IAsyncDisposable as the second argument.
  2. Fix the producer of disposable2 so it returns a real disposable or a null-object instead of null.
  3. Collect only non-null disposables and use the params or IEnumerable Create overload instead.

Example fix

// before
var composite = StableCompositeAsyncDisposable.Create(conn, maybeSub);
// after
var disposables = new List<IAsyncDisposable> { conn };
if (maybeSub != null) disposables.Add(maybeSub);
var composite = StableCompositeAsyncDisposable.Create(disposables);
Defensive patterns

Strategy: validation

Validate before calling

if (disposable2 is null) throw new ArgumentNullException(nameof(disposable2));
var composite = StableCompositeAsyncDisposable.Create(disposable1, disposable2);

Type guard

static bool IsDisposable(IAsyncDisposable? d) => d is not null;

Try / catch

try { var c = StableCompositeAsyncDisposable.Create(d1, d2); }
catch (ArgumentNullException ex) when (ex.ParamName == "disposable2")
{ log.LogWarning("disposable2 was null"); }

Prevention

When it happens

Trigger: Calling StableCompositeAsyncDisposable.Create(someDisposable, null) — null second argument, e.g. a subscription or stream that was never created.

Common situations: Conditional subscription logic ("only subscribe if enabled") that leaves the second disposable null; a library API returning null on failure; typos passing the wrong variable.

Related errors


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

Appendix: source

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

// 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.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

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);

View on GitHub (pinned to 94b5d5ab91)