devlooped/moq · error · ArgumentNullException
callback (Argument is null)
Error message
callback (Argument is null)
What it means
SetCallbackBehavior installs the delegate that runs when the mocked member is invoked; Moq requires a non-null callback because a setup whose callback is null would leave the call pipeline with no user behavior to execute and fail later at invocation time. The throw site is a standard ArgumentNullException guard: the faulty input is a null Delegate argument, e.g. mock.Setup(...).Callback(null) or a conditionally-built delegate that turned out to be null.
Solutions
- Pass a non-null lambda or delegate to Callback()
- Guard conditional callback selection so a default lambda is always provided
- If the callback is optional, skip calling .Callback() entirely instead of passing null
Example fix
// before mock.Setup(m => m.DoWork()).Callback(optionalAction); // after mock.Setup(m => m.DoWork()).Callback(() => optionalAction?.Invoke());
Defensive patterns
Strategy: validation
Validate before calling
if (callback == null) throw new InvalidOperationException("Callback delegate must not be null before Setup"); Type guard
static bool IsValidCallback(Delegate? d) => d is not null;
Try / catch
try { setup.Callback(cb); } catch (ArgumentNullException ex) when (ex.ParamName == "callback") { /* supply a default lambda */ } Prevention
- Never pass nullable delegates directly to Callback()
- Use ?? fallback lambdas for conditional callbacks
- Skip .Callback() entirely when no action is needed
When it happens
Trigger: Calling `.Callback(null)`, or passing a variable/ternary expression that evaluates to null, e.g. `.Callback(someCondition ? action1 : null)`.
Common situations: Conditionally selected callbacks where one branch is null; callbacks resolved from configuration or DI that weren't wired up.
Related errors
- Value cannot be null. (Parameter 'value')
- Value cannot be null. (Parameter 'value')
- Value cannot be null. (Parameter 'newExpression')
- Resources.InvalidCallbackParameterMismatch (formatted with…
- Resources.InvalidCallbackNotADelegateWithReturnTypeVoid
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/8ef487cbe33ea66c.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/MethodCall.cs:144
this.afterReturnCallback?.Execute(invocation);
}
public void SetCallBaseBehavior()
{
if (this.Mock.MockedType.IsDelegateType())
{
throw new NotSupportedException(Resources.CallBaseCannotBeUsedWithDelegateMocks);
}
this.returnOrThrow = ReturnBase.Instance;
}
public void SetCallbackBehavior(Delegate callback)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
ref Behavior? behavior = ref (this.returnOrThrow == null) ? ref this.callback
: ref this.afterReturnCallback;
if (callback is Action callbackWithoutArguments)
{
behavior = new Callback(_ => callbackWithoutArguments());
}
else if (callback.GetType() == typeof(Action<IInvocation>))
{
// NOTE: Do NOT rewrite the above condition as `callback is Action<IInvocation>`,
// because this will also yield true if `callback` is a `Action<object>` and thus
// break existing uses of `(object arg) => ...` callbacks!
behavior = new Callback((Action<IInvocation>)callback);
}
else
{View on GitHub (pinned to 89a5be629c)