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
- Pass a valid, constructed CancellationTokenSource to the constructor
- Use the parameterless CancellationAsyncDisposable() overload, which creates its own CTS
- 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
- Prefer the parameterless constructor when you don't already own a CTS
- Initialize CTS fields inline (new CancellationTokenSource()) rather than lazily
- Run cancellation-related code under nullable reference type analysis
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
- Value cannot be null. (Parameter 'subscribeAsync')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'source')
- Value cannot be null. (Parameter 'onNextAsync')
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)