{"record":{"id":"b1a559402f677214","repo":"devlooped/moq","slug":"resources-invalidcallbackparametercountmismatch-formatted","errorCode":null,"errorMessage":"Resources.InvalidCallbackParameterCountMismatch (formatted with expected and actual parameter counts)","messagePattern":"Resources\\.InvalidCallbackParameterCountMismatch \\(formatted with expected and actual parameter counts\\)","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/MethodCall.cs","lineNumber":397,"sourceCode":"        }\n\n        void ValidateNumberOfCallbackParameters(Delegate callback, MethodInfo callbackMethod)\n        {\n            var numberOfActualParameters = callbackMethod.GetParameters().Length;\n            if (callbackMethod.IsStatic)\n            {\n                if (callbackMethod.IsExtensionMethod() || callback.Target != null)\n                {\n                    numberOfActualParameters--;\n                }\n            }\n\n            if (numberOfActualParameters > 0)\n            {\n                var numberOfExpectedParameters = this.Method.GetParameters().Length;\n                if (numberOfActualParameters != numberOfExpectedParameters)\n                {\n                    throw new ArgumentException(\n                        string.Format(\n                            CultureInfo.CurrentCulture,\n                            Resources.InvalidCallbackParameterCountMismatch,\n                            numberOfExpectedParameters,\n                            numberOfActualParameters));\n                }\n            }\n        }\n\n        void ValidateCallbackReturnType(MethodInfo callbackMethod, Type expectedReturnType)\n        {\n            var actualReturnType = callbackMethod.ReturnType;\n\n            if (actualReturnType == typeof(void))\n            {\n                throw new ArgumentException(Resources.InvalidReturnsCallbackNotADelegateWithReturnType);\n            }\n","sourceCodeStart":379,"sourceCodeEnd":415,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/MethodCall.cs#L379-L415","documentation":"Moq validates that a Callback(...) delegate passed alongside Returns/Throws (via Setup with computed value behaviors) receives exactly the same number of parameters as the mocked method. This ArgumentException is thrown when the callback delegate's parameter count differs from the method's parameter count, so Moq could not bind invocation arguments to the callback.","triggerScenarios":"Calling Setup(...).Callback(lambdaWithDifferentArity).Returns(...)/.Throws(...) where the callback lambda declares more or fewer parameters than the mocked method (e.g. a 2-arg callback on a 1-arg method); using a static/extension method group whose effective parameter count mismatches.","commonSituations":"Refactoring a mocked method signature (adding/removing parameters) without updating the Callback lambda; copying a Callback from another setup; declaring a callback with optional or extra capture parameters.","solutions":["Change the Callback delegate so its parameter list matches the mocked method's parameter count and types exactly","If you don't need invocation arguments, use a parameterless Callback(() => ...)","Update the setup after any change to the mocked interface/method signature","Use It.IsAny<T>() placeholders in the setup expression to keep the setup resilient"],"exampleFix":"// before\nmock.Setup(x => x.Save(It.IsAny<string>(), It.IsAny<int>()))\n    .Callback((string name) => Console.WriteLine(name))\n    .Returns(true);\n// after\nmock.Setup(x => x.Save(It.IsAny<string>(), It.IsAny<int>()))\n    .Callback((string name, int count) => Console.WriteLine(name))\n    .Returns(true);","handlingStrategy":"validation","validationCode":"static void ValidateCallbackArity(MethodInfo mockedMethod, Delegate callback)\n{\n    int cbParams = callback.Method.GetParameters().Length;\n    int expected = mockedMethod.GetParameters().Length;\n    if (cbParams != 0 && cbParams != expected)\n        throw new InvalidOperationException(\n            $\"Callback has {cbParams} params but mocked method has {expected}\");\n}","typeGuard":"bool CallbackArityMatches<TMock>(Expression<Func<TMock, object>> setup, Delegate cb)\n{\n    var method = ((MethodCallExpression)setup.Body).Method;\n    int n = cb.Method.GetParameters().Length;\n    return n == 0 || n == method.GetParameters().Length;\n}","tryCatchPattern":"try\n{\n    mock.Setup(x => x.Save(It.IsAny<string>(), It.IsAny<int>()))\n        .Callback((string s, int i) => log(s, i))\n        .Returns(true);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"parameter\"))\n{\n    // fix the callback parameter count in the test\n    throw;\n}","preventionTips":["Keep Callback lambdas' parameters mirroring the mocked method's signature","Prefer parameterless Callback(() => ...) when arguments are not needed","Update all setups whenever a mocked interface signature changes (IDE refactorings)"],"tags":["moq","callback","argument-count","unit-testing"],"backgroundTag":"invalid-argument-value","analyzedSha":"89a5be629c752960fe403e95ff583e4ae6f00542","analyzedAt":"2026-09-16T05:31:39.496Z","contentChangedAt":"2026-09-16T05:31:39.496Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}