dotnet/reactive · error · ArgumentNullException
Value cannot be null. (Parameter 'dispose')
Error message
Value cannot be null. (Parameter 'dispose')
What it means
Disposable.Create(Action dispose) throws ArgumentNullException when the dispose action is null. Create builds an AnonymousDisposable that invokes the given action on disposal; a null action would make disposal a no-op silently or crash later, so the factory validates eagerly. The contract is documented in the method's XML docs.
Solutions
- Provide a real action; use Disposable.Empty if no cleanup is needed.
- Null-check the delegate before calling Create and fall back to Disposable.Empty.
- Ensure the callback field is initialized at declaration (e.g. = () => {}) rather than left null.
Example fix
// before var d = Disposable.Create(_cleanup); // _cleanup may be null // after var d = _cleanup != null ? Disposable.Create(_cleanup) : Disposable.Empty;
Defensive patterns
Strategy: validation
Validate before calling
if (cleanup == null) return Disposable.Empty; var d = Disposable.Create(cleanup);
Type guard
IDisposable TryCreate(Action cleanup) => cleanup == null ? Disposable.Empty : Disposable.Create(cleanup);
Try / catch
try { var d = Disposable.Create(dispose); } catch (ArgumentNullException ex) when (ex.ParamName == "dispose") { d = Disposable.Empty; } Prevention
- Initialize delegate fields at declaration
- Map 'no cleanup needed' to Disposable.Empty, not null
- Null-check optional callbacks before registering them
When it happens
Trigger: Disposable.Create(null), often when the action is built from a delegate field/parameter that is null (unassigned callback, optional hook), or from a ternary/LINQ selection that produced null.
Common situations: Registering cleanup callbacks where the cleanup delegate is conditionally assigned; passing a method group resolved via reflection or a dictionary of handlers that missed the key.
Related errors
- Value cannot be null. (Parameter 'disposable')
- Value cannot be null. (Parameter 'onNextAsync')
- Value cannot be null. (Parameter 'onErrorAsync')
- Value cannot be null. (Parameter 'onCompletedAsync')
- Value cannot be null. (Parameter 'second')
AI-assisted analysis of dotnet/reactive@94b5d5ab91 (2026-09-15).
Data as JSON: /api/errors/052c4c6b6d923f9d.
Report an issue: GitHub.
Appendix: source
Thrown at Rx.NET/Source/src/System.Reactive/Disposables/Disposable.cs:52
}
}
/// <summary>
/// Gets the disposable that does nothing when disposed.
/// </summary>
public static IDisposable Empty => EmptyDisposable.Instance;
/// <summary>
/// Creates a disposable object that invokes the specified action when disposed.
/// </summary>
/// <param name="dispose">Action to run during the first call to <see cref="IDisposable.Dispose"/>. The action is guaranteed to be run at most once.</param>
/// <returns>The disposable object that runs the given action upon disposal.</returns>
/// <exception cref="ArgumentNullException"><paramref name="dispose"/> is <c>null</c>.</exception>
public static IDisposable Create(Action dispose)
{
if (dispose == null)
{
throw new ArgumentNullException(nameof(dispose));
}
return new AnonymousDisposable(dispose);
}
/// <summary>
/// Creates a disposable object that invokes the specified action when disposed.
/// </summary>
/// <param name="state">The state to be passed to the action.</param>
/// <param name="dispose">Action to run during the first call to <see cref="IDisposable.Dispose"/>. The action is guaranteed to be run at most once.</param>
/// <returns>The disposable object that runs the given action upon disposal.</returns>
/// <exception cref="ArgumentNullException"><paramref name="dispose"/> is <c>null</c>.</exception>
public static IDisposable Create<TState>(TState state, Action<TState> dispose)
{
if (dispose == null)
{
throw new ArgumentNullException(nameof(dispose));
}View on GitHub (pinned to 94b5d5ab91)