devlooped/moq · error · ArgumentException

Resources.InvalidCallbackParameterMismatch (formatted with…

Error message

Resources.InvalidCallbackParameterMismatch (formatted with expected and actual parameter type lists)

What it means

SetCallbackBehavior throws this ArgumentException when the callback delegate's parameter types do not match the mocked method's parameter types. Moq validates via CompareParameterTypesTo so the callback receives the exact arguments of the invocation.

Solutions

  1. Update the Callback lambda so its parameter list exactly matches the mocked method's parameters in order and type
  2. If no parameters are needed, use a parameterless `Callback(() => ...)`
  3. Check overload resolution — ensure the setup targets the intended overload

Example fix

// before
mock.Setup(m => m.Save("key", 5)).Callback((int id) => log(id));
// after
mock.Setup(m => m.Save("key", 5)).Callback((string key, int id) => log(key, id));
Defensive patterns

Strategy: validation

Validate before calling

var cbParams = callback.GetMethodInfo().GetParameters();
var methodParams = method.GetParameters();
if (cbParams.Length != methodParams.Length) throw new InvalidOperationException("Callback parameter count must match mocked method");

Type guard

static bool CallbackParamsMatch(Delegate d, MethodInfo mocked) => d.GetMethodInfo().GetParameters().Select(p => p.ParameterType).SequenceEqual(mocked.GetParameters().Select(p => p.ParameterType));

Try / catch

try { setup.Callback(cb); } catch (ArgumentException ex) when (ex.Message.Contains("callback")) { /* align callback signature */ }

Prevention

When it happens

Trigger: `.Callback(lambda)` whose lambda parameters differ in count, order, or type from the mocked method, e.g. mocking `Save(string, int)` with `.Callback((int id) => ...)`.

Common situations: Refactorings that changed the mocked method signature without updating Callback lambdas; using a shared helper lambda across setups with different signatures.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16). Data as JSON: /api/errors/ab393aa6d9f1268e. Report an issue: GitHub.

Appendix: source

Thrown at src/Moq/MethodCall.cs:166

                                                                     : 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
            {
                var expectedParamTypes = this.Method.GetParameterTypes();
                if (!callback.CompareParameterTypesTo(expectedParamTypes))
                {
                    throw new ArgumentException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.InvalidCallbackParameterMismatch,
                            this.Method.GetParameterTypeList(),
                            callback.GetMethodInfo().GetParameterTypeList()));
                }

                var callbackMethod = callback.GetMethodInfo();

                if (callbackMethod.ReturnType != typeof(void))
                {
                    throw new ArgumentException(Resources.InvalidCallbackNotADelegateWithReturnTypeVoid, nameof(callback));
                }

                if (callbackMethod.GetParameterTypes().Any(Extensions.IsOrContainsTypeMatcher))
                {
                    throw new ArgumentException(Resources.TypeMatchersMayNotBeUsedWithCallbacks);
                }

View on GitHub (pinned to 89a5be629c)