PrismLibrary/Prism · error · ArgumentNullException

Resources.DelegateCommandDelegatesCannotBeNull

Error message

Resources.DelegateCommandDelegatesCannotBeNull

What it means

AsyncDelegateCommand requires a non-null execute delegate (and, when using the two-argument constructor, a non-null canExecute delegate). The constructor throws ArgumentNullException with Resources.DelegateCommandDelegatesCannotBeNull when either is null, because a command that cannot execute anything is meaningless.

Solutions

  1. Pass a valid Func<CancellationToken, Task> to the constructor.
  2. Check any factory/lambda producing the delegate for null before constructing the command.
  3. Use the canExecute-aware constructor only when you actually have a non-null canExecute Func<bool>; otherwise use the single-argument overload.

Example fix

// before
public MyViewModel()
{
    SaveCommand = new AsyncDelegateCommand(_saveFunc); // _saveFunc is null
}
// after
public MyViewModel()
{
    SaveCommand = new AsyncDelegateCommand(async ct => await SaveAsync(ct), () => CanSave);
}
Defensive patterns

Strategy: validation

Validate before calling

if (executeMethod == null) throw new InvalidOperationException("execute delegate required before constructing AsyncDelegateCommand");

Type guard

bool IsValidCommand(Func<CancellationToken, Task> exec, Func<bool> canExec) => exec != null && canExec != null;

Try / catch

try { SaveCommand = new AsyncDelegateCommand(handler); }
catch (ArgumentNullException ex) { logger.LogError(ex, "AsyncDelegateCommand delegate was null"); }

Prevention

When it happens

Trigger: new AsyncDelegateCommand(null) or new AsyncDelegateCommand(someMethodThatReturnsNull, canExecute) — e.g. passing a method group that resolves to null via reflection, or a factory returning null delegates.

Common situations: Wiring commands in a ViewModel constructor where the delegate comes from a nullable field or injected service that returned null; refactoring that renamed the target method leaving a null delegate; DI container failing to supply the method.

Related errors


AI-assisted analysis of PrismLibrary/Prism@358118cd64 (2026-09-15). Data as JSON: /api/errors/fd3f33f4cb741880. Report an issue: GitHub.

Appendix: source

Thrown at src/Prism.Core/Commands/AsyncDelegateCommand.cs:71

#if NET6_0_OR_GREATER
        : this(c => executeMethod().WaitAsync(c), canExecuteMethod)
#else
        : this(c => executeMethod(), canExecuteMethod)
#endif
    {
    }

    /// <summary>
    /// Creates a new instance of <see cref="DelegateCommand"/> with the <see cref="Func{Task}"/> to invoke on execution
    /// and a <see langword="Func" /> to query for determining if the command can execute.
    /// </summary>
    /// <param name="executeMethod">The <see cref="Func{CancellationToken, Task}"/> to invoke when <see cref="ICommand.Execute"/> is called.</param>
    /// <param name="canExecuteMethod">The delegate to invoke when <see cref="ICommand.CanExecute"/> is called</param>
    public AsyncDelegateCommand(Func<CancellationToken, Task> executeMethod, Func<bool> canExecuteMethod)
        : base()
    {
        if (executeMethod == null || canExecuteMethod == null)
            throw new ArgumentNullException(nameof(executeMethod), Resources.DelegateCommandDelegatesCannotBeNull);

        _executeMethod = executeMethod;
        _canExecuteMethod = canExecuteMethod;
    }

    /// <summary>
    /// Gets the current state of the AsyncDelegateCommand
    /// </summary>
    public bool IsExecuting
    {
        get => _isExecuting;
        private set => SetProperty(ref _isExecuting, value, OnCanExecuteChanged);
    }

    ///<summary>
    /// Executes the command.
    ///</summary>
    public async Task Execute(CancellationToken? cancellationToken = null)

View on GitHub (pinned to 358118cd64)