dotnet/efcore · error · InvalidOperationException

Invocation: couldn't find method '{methodSymbol.Name}' on ty

Error message

Invocation: couldn't find method '{methodSymbol.Name}' on type '{declaringType.Name}': {invocation}

What it means

For a non-generic method, the Roslyn symbol resolved but reflection's declaringType.GetMethod(name, bindingFlags, paramTypes) returned null. The method exists to Roslyn but is not discoverable via reflection with the exact parameter types, so the translator cannot build the MethodCallExpression.

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 dbf9771522)

Solutions

  1. Make the method public
  2. Add [InternalsVisibleTo] for the assembly consuming the query
  3. Avoid by-ref/out/in parameters in methods called from precompiled queries
  4. Pin the referenced assembly version so reflection sees the same signature

Example fix

// before (internal, by-ref)
internal static int Compute(ref int x) { ... }
// after (public, by-value)
public static int Compute(int x) { ... }
Defensive patterns

Strategy: validation

Validate before calling

// Confirm the method is reflection-discoverable with the exact signature.
var mi = typeof(MyType).GetMethod(nameof(MyType.M),
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static,
    new[] { typeof(int) });
if (mi is null) { /* make public or add InternalsVisibleTo */ }

Prevention

When it happens

Trigger: The resolved method is internal/private across an assembly boundary without InternalsVisibleTo, has by-ref/out/in parameters or custom modifiers that don't match reflection's parameter types exactly, or the declaring type loaded via reflection differs from the Roslyn type (different assembly version).

Common situations: Calling internal extension methods from another assembly; methods with ref/out/in parameters; COM/interop methods; methods on types from a different assembly version than what the runtime loads.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/df1bcba40706ef1b. Report an issue: GitHub.