AvaloniaUI/Avalonia · error · ArgumentNullException

Value cannot be null. (Parameter 'dispose')

Error message

Value cannot be null. (Parameter 'dispose')

What it means

Thrown by Disposable.Create(Action) when the dispose delegate passed in is null. Disposable is an internal Avalonia helper (mirroring System.Reactive's Disposable) that builds an AnonymousDisposable running the given action exactly once. The null guard exists because invoking a null delegate on disposal would otherwise throw a NullReferenceException later, far from the cause.

Source

Thrown at src/Avalonia.Base/Reactive/Disposable.cs:76

        }
    }

    /// <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 11c5427268)

Solutions

  1. Pass a non-null Action (even an empty lambda () => { }) to Create.
  2. If the cleanup is conditional, build the Action before calling Create and default it to a no-op instead of null.
  3. Trace the stack to the Avalonia subsystem that invoked Create and fix the null source there.

Example fix

// before
var d = Disposable.Create(cleanup as Action); // cleanup may be null
// after
var d = Disposable.Create(cleanup ?? (() => { }));
Defensive patterns

Strategy: validation

Validate before calling

if (dispose is null) throw new ArgumentNullException(nameof(dispose));
var d = Disposable.Create(dispose);

Type guard

static bool IsValidDisposeAction(Action? a) => a is not null;

Prevention

When it happens

Trigger: Calling Disposable.Create(null) or Disposable.Create(someExpressionThatEvaluatesToNull). This is framework-internal code, typically reached via an Avalonia subsystem that wraps a cleanup callback (event unsubscription, handle release) in a disposable.

Common situations: A refactor removes the cleanup body and leaves a null literal; a conditional that yields a null Action under an edge branch is passed in; a third-party integration hands Avalonia a null teardown callback.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/97f123ebb35cbf46. Report an issue: GitHub.