devlooped/moq · error · ArgumentException
Can't set return value for void method
Error message
Can't set return value for void method {0}. What it means
Moq's Protected() API throws this ArgumentException when you attempt to set up a return value for a method that has a void return type. Void methods have nothing to return, so a Returns/ReturnsAsync setup is meaningless and the library rejects it eagerly at setup time.
Solutions
- Remove the Returns(...) call; for void protected methods use Protected().Setup(...) with callbacks only (e.g. .Callback(...)) or just mock.Setup(...) raising events
- If a value is needed, change the protected method signature to return a value, or verify the void call instead with Protected().Verify(...)
Example fix
// before
mock.Protected().Setup("OnChanged").Returns(true); // OnChanged is void
// after
mock.Protected().Setup("OnChanged").Callback(() => changed = true); Defensive patterns
Strategy: validation
Validate before calling
if (methodInfo.ReturnType == typeof(void)) throw new InvalidOperationException("Do not call Returns on a void method: " + methodInfo.Name); Try / catch
try { mock.Protected().Setup("OnChanged").Returns(true); } catch (ArgumentException ex) { /* drop the Returns or use Callback */ } Prevention
- Only chain Returns/ReturnsAsync on members with non-void return types
- Use .Callback/.Raises for void protected methods
- Check the protected member signature before writing setups
When it happens
Trigger: Calling Protected().Setup(...) with a Returns(...) (or SetupSequence with returns) on a protected method whose MethodInfo.ReturnType is typeof(void), e.g. a protected void OnSomething() method.
Common situations: Copy-pasting a setup from a non-void method onto a protected event-raiser or callback-style void method; expecting Setup to also register a callback for void members.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Use ItExpr.IsNull rather than a null argument value, as it…
- Unsupported expression
- Unsupported expression
- Expression is not a property access
- Type to mock ( ) must be an interface, a delegate, or a…
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/abd26af0d248b6ee.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/Protected/ProtectedMock.cs:451
}
static void ThrowIfPublicSetter(PropertyInfo property, string reflectedTypeName)
{
if (property.CanWrite(out var setter) && setter.IsPublic)
{
throw new ArgumentException(string.Format(
CultureInfo.CurrentCulture,
Resources.UnexpectedPublicProperty,
reflectedTypeName,
property.Name));
}
}
static void ThrowIfVoidMethod(MethodInfo method)
{
if (method.ReturnType == typeof(void))
{
throw new ArgumentException(Resources.CantSetReturnValueForVoid);
}
}
static Type?[] ToArgTypes(object[] args)
{
if (args == null)
{
throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);
}
var types = new Type?[args.Length];
for (int index = 0; index < args.Length; index++)
{
if (args[index] == null)
{
throw new ArgumentException(Resources.UseItExprIsNullRatherThanNullArgumentValue);
}
View on GitHub (pinned to 89a5be629c)