dotnet/reactive · error · ArgumentNullException

Value cannot be null. (Parameter 'cts')

Error message

Value cannot be null. (Parameter 'cts')

What it means

CancellationAsyncDisposable wraps a CancellationTokenSource so disposal cancels it. The constructor validates its 'cts' argument and throws ArgumentNullException when a null CancellationTokenSource is supplied, because the Token property and DisposeAsync would otherwise throw NullReferenceException later.

Solutions

  1. Pass a valid, constructed CancellationTokenSource to the constructor
  2. Use the parameterless CancellationAsyncDisposable() overload, which creates its own CTS
  3. Null-check the cts before constructing

Example fix

// before
var d = new CancellationAsyncDisposable(_cts); // _cts is null here
// after
_cts ??= new CancellationTokenSource();
var d = new CancellationAsyncDisposable(_cts);
Defensive patterns

Strategy: validation

Validate before calling

if (cts == null) cts = new CancellationTokenSource();

Type guard

bool IsValidCts(CancellationTokenSource? cts) => cts is not null;

Try / catch

try { var d = new CancellationAsyncDisposable(cts); } catch (ArgumentNullException ex) when (ex.ParamName == "cts") { d = new CancellationAsyncDisposable(); }

Prevention

When it happens

Trigger: new CancellationAsyncDisposable((CancellationTokenSource)null), or passing a cts field/property that was never initialized or was set to null.

Common situations: Storing a CTS in a field initialized lazily; receiving a null token source from another component; passing null when intending to use the parameterless constructor.

Related errors


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

Appendix: source

Thrown at AsyncRx.NET/System.Reactive.Async/Disposables/CancellationAsyncDisposable.cs:21

// See the LICENSE file in the project root for more information. 

using System.Threading;
using System.Threading.Tasks;

namespace System.Reactive.Disposables
{
    public sealed class CancellationAsyncDisposable : IAsyncDisposable
    {
        private readonly CancellationTokenSource _cts;

        public CancellationAsyncDisposable()
            : this(new CancellationTokenSource())
        {
        }

        public CancellationAsyncDisposable(CancellationTokenSource cts)
        {
            _cts = cts ?? throw new ArgumentNullException(nameof(cts));
        }

        public CancellationToken Token => _cts.Token;

        public ValueTask DisposeAsync()
        {
            _cts.Cancel();

            return default;
        }
    }
}

View on GitHub (pinned to 94b5d5ab91)