devlooped/moq · error · ArgumentException
Could not determine the correct positions for all argument…
Error message
Could not determine the correct positions for all argument matchers ({0} in total) used in a call to this method: {1}.
This could be caused by an unrecognized type conversion, coercion, narrowing, or widening, and is most likely a bug in Moq. Please report your use case to the Moq team. What it means
During expression reconstruction Moq must map each recorded argument matcher back to a positional parameter of the invoked method. If leftover matchers remain after distribution (matchIndex < matches.Length), Moq cannot determine correct positions and throws ArgumentException, explicitly noting this is likely a Moq bug caused by an unrecognized type conversion/coercion/narrowing/widening.
Solutions
- Make matcher types exactly match the parameter types (use It.IsAny<short>() for a short parameter, not It.IsAny<int>()).
- Remove implicit conversions by casting explicitly so Moq can correlate matchers to positions.
- Disambiguate the target overload (cast the lambda or use explicit delegate types) so the recorded invocation matches the declared method.
- If types already match exactly, this is the suspected Moq bug the message mentions — reduce to a minimal repro and report it to the Moq team.
Example fix
// before mock.SetupAction(x => x.Write(It.IsAny<int>())); // parameter is short // after mock.SetupAction(x => x.Write(It.IsAny<short>()));
Defensive patterns
Strategy: validation
Validate before calling
// Match It.IsAny<T> type arguments exactly to parameter types Debug.Assert(matcherTypes.Zip(paramTypes, (m, p) => m == p).All(x => x), "Matcher/parameter type mismatch");
Type guard
static bool MatchersAlign(MethodInfo method, Type[] matcherTypes) =>
method.GetParameters().Select(p => p.ParameterType).SequenceEqual(matcherTypes); Try / catch
try
{
mock.SetupAction(lambda);
}
catch (ArgumentException ex) when (ex.Message.Contains("positions for all argument matchers"))
{
throw new InvalidOperationException("Matcher types must exactly match parameter types; otherwise report to Moq.", ex);
} Prevention
- Use It.IsAny<T>() with T exactly equal to the parameter type (no implicit conversions)
- Avoid ambiguous overloads in setups; cast the lambda or delegate to pick the exact overload
- Watch for boxing of value types when passing matchers
- Treat this message as a probable Moq bug: build a minimal repro if types already match
When it happens
Trigger: Using argument matchers (It.IsAny<T>(), It.Is<T>(...)) inside a delegate-based setup where the number or arity of matchers does not line up with the invocation's parameters — typically via implicit conversions or overloads between matcher type and parameter type.
Common situations: Matchers with implicit numeric conversions (It.IsAny<int>() passed where a short/long/enum is expected); overloaded methods where the compiled delegate binds a different overload than the recorded invocation; boxing/casting of matcher arguments; generic type inference picking a mismatched matcher arity.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Unsupported expression
- The return type of the last member shown above is not…
- Value cannot be null. (Parameter 'value')
- Unsupported expression
- Expression is not a property access
AI-assisted analysis of devlooped/moq@89a5be629c (2026-09-16).
Data as JSON: /api/errors/80927c2ce27e6510.
Report an issue: GitHub.
Appendix: source
Thrown at src/Moq/ActionObserver.cs:176
// * the remaining matchers can't be distributed over the remaining parameters.
// In this case, we bail out, which will lead to an exception being thrown.
break;
}
// The remaining matchers can be distributed over the remaining parameters,
// so we can use up this matcher:
expressions[argumentIndex] = new MatchExpression(matches[matchIndex]);
++matchIndex;
}
}
if (matchIndex < matches.Length)
{
// If we get here, we can be almost certain that matchers weren't distributed properly
// across the invocation's parameters. We could hope for the best and just leave it
// at that; however, it's probably better to let client code know, so it can be either
// adjusted or reported to Moq.
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.MatcherAssignmentFailedDuringExpressionReconstruction,
matches.Length,
$"{invocation.Method.DeclaringType!.GetFormattedName()}.{invocation.Method.Name}"));
}
bool CanDistribute(int msi, int asi)
{
var match = matches[msi];
var matchType = match.RenderExpression.Type;
for (int ai = asi; ai < expressions.Length; ++ai)
{
if (parameterTypes[ai].IsAssignableFrom(matchType)
&& CanDistribute(msi + 1, ai + 1))
{
return true;
}View on GitHub (pinned to 89a5be629c)