dotnet/efcore · error · InvalidOperationException
Invocation: couldn't find method
Error message
Invocation: couldn't find method '{methodSymbol.Name}' on type '{declaringType.Name}': {invocation} What it means
Thrown when a non-generic method cannot be found on the declaring type via reflection GetMethod(name, bindings, paramTypes). The Roslyn symbol gave the method name and parameter types, but Type.GetMethod returned null. This means Roslyn sees the method but the loaded CLR type does not expose it under the same name and signature.
Solutions
- Verify the method is public or that InternalsVisibleTo is set for the precompilation assembly.
- Check for assembly version mismatches — ensure all referenced packages are at consistent versions between compile and precompile phases.
- If the method is an explicit interface implementation, call it through the interface type instead of the implementing type.
- Pass the external assembly containing the declaring type via the additionalAssembly parameter of CSharpToLinqTranslator.Load().
- If the method has ref/out/in parameters, the translator's parameter-type resolution may not match the reflection signature — restructure to avoid passing by reference.
Example fix
// before — calling internal method from different assembly var query = ctx.Items.Where(x => x.CalculateInternalScore() > 10); // after — make method public, or move logic into the query var query = ctx.Items.Where(x => x.Score > 10);
Defensive patterns
Strategy: validation
Validate before calling
// Before precompiling, verify non-generic methods are findable via reflection
foreach (var invocation in querySyntaxTree.DescendantNodes().OfType<InvocationExpressionSyntax>())
{
if (semanticModel.GetSymbolInfo(invocation).Symbol is IMethodSymbol { IsGenericMethod: false } method)
{
var declaringType = ResolveTypeForCheck(method.ContainingType);
var paramTypes = method.Parameters.Select(p => ResolveTypeForCheck(p.Type)).ToArray();
var found = declaringType.GetMethod(method.Name,
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
null, CallingConventions.Any, paramTypes, null);
if (found is null)
ReportError($"Method '{method.Name}' not found via reflection on {declaringType.Name}");
}
} Prevention
- Make methods called in precompiled queries public, or add InternalsVisibleTo for the precompilation assembly.
- Avoid ref/out/in parameters in methods called from precompiled queries.
- Keep all package versions consistent between compile and precompile phases.
- Pass external assemblies via additionalAssembly to Load().
- Avoid explicit interface implementation method calls.
When it happens
Trigger: A precompiled query calls a non-generic instance or static method where: the method is private/internal and BindingFlags resolution differs; the method's parameter types resolved through ResolveType differ from the actual reflection parameter types; the declaring type loaded at runtime is a different version than what Roslyn compiled against; the method is an explicit interface implementation (maps to a different name in metadata); or the method is compiler-generated.
Common situations: Calling internal methods from a different assembly without InternalsVisibleTo; version skew between the NuGet package referenced at compile time and the one loaded at runtime; calling methods on types from assemblies not passed via additionalAssembly; explicit interface implementation methods whose metadata name includes the interface prefix; methods with optional/ref parameters that change the reflection signature lookup.
Related errors
- Invocation: Found matches for generic method
- MemberAccess: couldn't find member
- Couldn't find single Add method on type
- ObjectCreation: Missing constructor
- ArrayCreation: multi-dimensional array
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/df1bcba40706ef1b.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:647
}
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)
{
throw new InvalidOperationException(
$"Invocation: couldn't find method '{methodSymbol.Name}' on type '{declaringType.Name}': {invocation}");
}
}
// We have the reflection MethodInfo for the method, prepare the arguments.
// We can have less arguments than parameters when the method has optional parameters; fill in the missing ones with the default
// value.
// If the method also has a "params" parameter, we also need to take care of that - the syntactic arguments will need to be packed
// into the "params" array etc.
var parameters = methodInfo.GetParameters();
var sourceArguments = invocation.ArgumentList.Arguments;
var destArguments = new Expression?[parameters.Length];
var paramIndex = 0;
// At the syntactic level, an extension method invocation looks like a normal instance's.
// Prepend the instance to the argument list.
// TODO: Test invoking extension without extension syntax (as static)View on GitHub (pinned to 3a2006ef56)