devlooped/moq · error · ArgumentException
Resources.TypeMatchersMayNotBeUsedWithCallbacks
Error message
Resources.TypeMatchersMayNotBeUsedWithCallbacks
What it means
SetCallbackBehavior throws this ArgumentException when a callback delegate's parameter types contain a Moq type matcher (It.IsAny<T>, It.Is<T>, It.Ref). Type matchers are only meaningful in setup argument expressions, not inside callbacks, which receive concrete invocation arguments.
Solutions
- Replace matcher types in the callback signature with the concrete parameter types
- Use It matchers only in the setup argument list, before the callback
- Filter within the callback body with plain if-conditions instead of matchers
Example fix
// before mock.Setup(m => m.Save(It.IsAny<string>())).Callback((It.IsAny<string> s) => log(s)); // after mock.Setup(m => m.Save(It.IsAny<string>())).Callback((string s) => log(s));
Defensive patterns
Strategy: type-guard
Validate before calling
foreach (var p in callback.GetMethodInfo().GetParameters())
if (p.ParameterType.FullName?.StartsWith("Moq.It") == true) throw new InvalidOperationException("Type matchers not allowed in callback params"); Type guard
static bool HasNoTypeMatchers(Delegate d) => !d.GetMethodInfo().GetParameters().Any(p => p.ParameterType.IsGenericType && p.ParameterType.GetGenericTypeDefinition().Namespace == "Moq");
Try / catch
try { setup.Callback(cb); } catch (ArgumentException ex) when (ex.Message.Contains("Type matchers")) { /* use concrete types in callback signature */ } Prevention
- Use It.* only in setup argument expressions
- Declare callback params with concrete types
- Never copy matcher types into lambda signatures
When it happens
Trigger: `.Callback((It.IsAny<int> x) => ...)` or passing a delegate whose signature uses Moq matcher types as callback parameters.
Common situations: Copy-pasting the setup's matcher expression into the Callback lambda signature; misunderstanding that callbacks receive actual runtime values.
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
- callback (Argument is null)
- Resources.InvalidCallbackParameterMismatch (formatted with…
- Resources.InvalidCallbackNotADelegateWithReturnTypeVoid
- Resources.InvalidCallbackParameterCountMismatch (formatted…
- Resources.InvalidReturnsCallbackNotADelegateWithReturnType
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/c34b51d243e02990.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/MethodCall.cs:183
{
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);
}
behavior = new Callback(invocation => callback.InvokePreserveStack(invocation.Arguments));
}
}
public void SetFailMessage(string failMessage)
{
this.failMessage = failMessage;
}
public void SetRaiseEventBehavior<TMock>(Action<TMock> eventExpression, Delegate func)
where TMock : class
{
Guard.NotNull(eventExpression, nameof(eventExpression));
var expression = ExpressionReconstructor.Instance.ReconstructExpression(eventExpression, this.Mock.ConstructorArguments);
View on GitHub (pinned to 89a5be629c)