dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'cts')
Error message
Value cannot be null. (Parameter 'cts')
What it means
CancellationDisposable's constructor accepts an existing CancellationTokenSource and stores it as the source it will cancel on Dispose. A null cts has nothing to cancel, so the constructor throws ArgumentNullException immediately.
Solutions
- Ensure the CancellationTokenSource is initialized before constructing the disposable (e.g. cts ??= new CancellationTokenSource())
- If you have no existing source, call the parameterless constructor CancellationDisposable() which creates its own CTS
- If the value is legitimately nullable, guard: if (cts != null) new CancellationDisposable(cts); else new CancellationDisposable()
Example fix
// before CancellationDisposable cd = new CancellationDisposable(_cts); // _cts may be null // after CancellationDisposable cd = new CancellationDisposable(_cts ?? new CancellationTokenSource());
Defensive patterns
Strategy: type-guard
Validate before calling
if (cts == null) cts = new CancellationTokenSource(); var cd = new CancellationDisposable(cts);
Type guard
CancellationDisposable SafeCreate(CancellationTokenSource? cts) => cts is null ? new CancellationDisposable() : new CancellationDisposable(cts);
Try / catch
try { return new CancellationDisposable(cts); }
catch (ArgumentNullException) { return new CancellationDisposable(); } Prevention
- Initialize CancellationTokenSource fields at declaration
- Use the parameterless constructor when you don't own a source
- Treat CTS fields as non-nullable where possible
When it happens
Trigger: new CancellationDisposable((CancellationTokenSource)null) — typically when the CTS comes from a field, property, method parameter, or linked-source helper that was never initialized.
Common situations: Passing a CancellationTokenSource obtained from an API that can return null; refactoring where a nullable CTS field is passed without a check.
Related errors
- Value cannot be null. (Parameter 'disposables')
- Value cannot be null. (Parameter 'item')
- Value cannot be null. (Parameter 'observer')
- Value cannot be null. (Parameter 'observableFactory')
- observableFactory
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/adafff35d03b3302.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Disposables/CancellationDisposable.cs:23
using System.Threading;
namespace System.Reactive.Disposables
{
/// <summary>
/// Represents a disposable resource that has an associated <seealso cref="CancellationToken"/> that will be set to the cancellation requested state upon disposal.
/// </summary>
public sealed class CancellationDisposable : ICancelable
{
private readonly CancellationTokenSource _cts;
/// <summary>
/// Initializes a new instance of the <see cref="CancellationDisposable"/> class that uses an existing <seealso cref="CancellationTokenSource"/>.
/// </summary>
/// <param name="cts"><seealso cref="CancellationTokenSource"/> used for cancellation.</param>
/// <exception cref="ArgumentNullException"><paramref name="cts"/> is <c>null</c>.</exception>
public CancellationDisposable(CancellationTokenSource cts)
{
_cts = cts ?? throw new ArgumentNullException(nameof(cts));
}
/// <summary>
/// Initializes a new instance of the <see cref="CancellationDisposable"/> class that uses a new <seealso cref="CancellationTokenSource"/>.
/// </summary>
public CancellationDisposable()
: this(new CancellationTokenSource())
{
}
/// <summary>
/// Gets the <see cref="CancellationToken"/> used by this <see cref="CancellationDisposable"/>.
/// </summary>
public CancellationToken Token => _cts.Token;
/// <summary>
/// Cancels the underlying <seealso cref="CancellationTokenSource"/>.
/// </summary>View on GitHub (pinned to 94b5d5ab91)