dotnet/efcore · error · InvalidOperationException
Invocation: Found matches for generic method
Error message
Invocation: Found {definitionMethodInfos.Length} matches for generic method: {invocation} What it means
Thrown when resolving a generic method's open definition via reflection yields zero or more than one match. After building a detailed signature comparison (name, generic arity, parameter count, and resolved parameter types mapped through generic type parameters), the translator expects exactly one candidate. If it finds 0 or 2+ matches, the Roslyn symbol and the reflection metadata are inconsistent and it throws InvalidOperationException.
Solutions
- Reduce ambiguity: if you control the method, rename overloads so only one generic method with that name and arity exists on the type.
- Check for assembly version mismatches between the compilation references and the runtime-loaded assemblies — ensure the same version of all packages is used consistently.
- If the method is an extension method, try calling it as a static method explicitly to see if that resolves the ambiguity differently.
- Simplify the generic call — avoid using methods where the same name appears with the same arity and parameter count but different constraints or type mappings.
Example fix
// before — ambiguous overloads // public static T Pick<T>(this T a, T b); // public static T Pick<T>(this T a, T b) where T: struct; var query = ctx.Values.Select(x => MyExtensions.Pick(x, x)); // after — disambiguate by renaming or using a non-ambiguous helper var query = ctx.Values.Select(x => x);
Defensive patterns
Strategy: validation
Validate before calling
// Before precompiling, verify generic methods have unambiguous reflection resolution
foreach (var invocation in querySyntaxTree.DescendantNodes().OfType<InvocationExpressionSyntax>())
{
if (semanticModel.GetSymbolInfo(invocation).Symbol is IMethodSymbol { IsGenericMethod: true } method)
{
var declaringType = ResolveTypeForCheck(method.ContainingType);
var matches = declaringType.GetMethods()
.Count(m => m.Name == method.Name && m.IsGenericMethodDefinition
&& m.GetGenericArguments().Length == method.OriginalDefinition.TypeParameters.Length);
if (matches != 1)
ReportError($"Ambiguous generic method '{method.Name}' has {matches} reflection matches");
}
} Prevention
- Avoid generic methods with overloads that share the same name and arity on the same type.
- Ensure assembly versions are consistent between compile-time and precompilation-time references.
- Keep generic extension method usage simple — prefer distinct method names for different overloads.
- Test precompilation of generic-heavy query code in CI to catch ambiguity early.
When it happens
Trigger: A precompiled query calls a generic method where: (a) reflection GetMethods returns multiple methods matching the same name/arity/parameter-signature after type-parameter resolution (ambiguous overloads in the declaring type), or (b) no method matches because the Roslyn-resolved parameter types differ from the reflection parameter types (e.g. due to type forwarding, remapped types, or compiler-generated wrapper types).
Common situations: Calling custom generic extension methods with overloaded signatures that differ only in generic constraints; calling framework generic methods whose containing type was loaded from a different assembly version than Roslyn analyzed; using F# or VB-compiled libraries where generic parameter naming conventions differ; calling methods with ref/out or in parameters that the translator's parameter-type resolution handles differently.
Related errors
- Invocation: couldn't find method
- Couldn't find single Add method on type
- MemberAccess: couldn't find member
- ObjectCreation: Missing constructor
- ArrayCreation: multi-dimensional array
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/787f3a469f7f1115.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:627
for (var i = 0; i < candidateParams.Length; i++)
{
var translatedParamType = ResolveType(originalDefinition.Parameters[i].Type, methodTypeParameterMap);
if (translatedParamType != candidateParams[i].ParameterType)
{
return false;
}
}
return true;
}
return false;
}).ToArray();
if (definitionMethodInfos.Length != 1)
{
throw new InvalidOperationException(
$"Invocation: Found {definitionMethodInfos.Length} matches for generic method: {invocation}");
}
var definitionMethodInfo = definitionMethodInfos[0];
var typeParams = methodSymbol.TypeArguments.Select(a => ResolveType(a)).ToArray();
methodInfo = definitionMethodInfo.MakeGenericMethod(typeParams);
}
else
{
// Non-generic method
var reducedMethodSymbol = methodSymbol.ReducedFrom ?? methodSymbol;
methodInfo = declaringType.GetMethod(
methodSymbol.Name,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
reducedMethodSymbol.Parameters.Select(p => ResolveType(p.Type)).ToArray());
if (methodInfo is null)View on GitHub (pinned to 3a2006ef56)