{"record":{"id":"865be90c69f6d626","repo":"devlooped/moq","slug":"resources-invalidreturnscallbacknotadelegatewithreturntype","errorCode":null,"errorMessage":"Resources.InvalidReturnsCallbackNotADelegateWithReturnType","messagePattern":"Resources\\.InvalidReturnsCallbackNotADelegateWithReturnType","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Moq/MethodCall.cs","lineNumber":413,"sourceCode":"                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\n            if (!expectedReturnType.IsAssignableFrom(actualReturnType))\n            {\n                // TODO: If the return type is a matcher, does the callback's return type need to be matched against it?\n                if (typeof(ITypeMatcher).IsAssignableFrom(expectedReturnType) == false)\n                {\n                    throw new ArgumentException(\n                        string.Format(\n                            CultureInfo.CurrentCulture,\n                            Resources.InvalidCallbackReturnTypeMismatch,\n                            expectedReturnType.GetFormattedName(),\n                            actualReturnType.GetFormattedName()));\n                }\n            }\n        }\n    }\n}","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/devlooped/moq/blob/89a5be629c752960fe403e95ff583e4ae6f00542/src/Moq/MethodCall.cs#L395-L431","documentation":"When a Callback is combined with Returns (or Throws) computed-value behavior, Moq requires the callback delegate to return a value assignable to the mocked method's return type. This ArgumentException is thrown when the callback delegate's return type is void, i.e. it is an Action-style delegate used where a Func-style delegate with a return type is required.","triggerScenarios":"Calling Setup(x => x.Method()).Callback<T>(a void-returning delegate).Returns(...) — e.g. passing an Action<T> or a lambda like x => Console.WriteLine(x) in a position where the computed return value must come from the callback's return value.","commonSituations":"Mixing up Callback(...) with Returns(callback) — the void delegate belongs in Callback, while Returns needs a Func; converting a setup from Callback+field-capture style to Returns-computed style; refactoring where a void helper method was passed directly.","solutions":["Replace the void-returning delegate with a Func whose return type matches (or is assignable to) the mocked method's return type","If you only want a side effect, use .Callback(...) for the side effect and .Returns(value) for the result","Ensure the lambda's last expression returns a value of the expected type"],"exampleFix":"// before\nmock.Setup(x => x.Compute(It.IsAny<int>()))\n    .Returns((int i) => Console.WriteLine(i)); // void lambda\n// after\nmock.Setup(x => x.Compute(It.IsAny<int>()))\n    .Returns((int i) => i * 2);","handlingStrategy":"validation","validationCode":"static void ValidateReturnsCallback(MethodInfo mockedMethod, Delegate cb)\n{\n    if (cb.Method.ReturnType == typeof(void))\n        throw new InvalidOperationException(\n            \"Returns callback must return a value; use Callback() for side effects\");\n}","typeGuard":"static bool IsValidReturnsCallback<TMethod>(Expression<Func<TMethod, object>> _, Delegate cb)\n    => cb.Method.ReturnType != typeof(void);","tryCatchPattern":"try\n{\n    mock.Setup(x => x.Compute(It.IsAny<int>()))\n        .Returns((int i) => i * 2);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"return type\"))\n{\n    // replace void delegate with a Func returning the expected type\n    throw;\n}","preventionTips":["Use Callback(...) for side effects and Returns(...) only with value-returning delegates","Check that lambdas passed to Returns have a non-void result","Avoid passing Action delegates into Returns<T>"],"tags":["moq","callback","return-type","unit-testing"],"backgroundTag":"type-mismatch","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"}