dotnet/efcore · error · NotSupportedException
Invocation over non-member access
Error message
Invocation over non-member access: {invocation} What it means
Thrown when an instance method or extension method invocation's syntactic expression is not a MemberAccessExpressionSyntax. The translator assumes that for non-static (or extension) methods, the invocation sits on top of a member access like `receiver.Method(args)`. When the invocation node is something else — e.g. a parenthesized expression, a cast-then-call, or a delegate invocation — it throws NotSupportedException because it cannot extract the receiver expression.
Solutions
- Extract the cast or intermediate computation into a separate local variable so the method call becomes a clean member access on that variable: `var typed = (MyType)obj; typed.Method();`
- Replace delegate invocations with direct method calls that Roslyn can resolve as member accesses.
- Avoid parenthesized casts immediately before method calls inside precompiled query lambdas — break them into steps.
- If using conditional access (x?.Method()), restructure to an explicit null check or use a helper method that the translator can visit normally.
Example fix
// before var query = ctx.Blogs.Where(b => ((dynamic)b.Meta).Active); // after var query = ctx.Blogs.Where(b => b.Meta != null && b.Meta.Active);
Defensive patterns
Strategy: validation
Validate before calling
// Before precompiling, check that instance method invocations are member accesses
var nonMemberInvocations = querySyntaxTree.DescendantNodes()
.OfType<InvocationExpressionSyntax>()
.Where(i =>
{
var symbol = semanticModel.GetSymbolInfo(i).Symbol as IMethodSymbol;
return symbol is { IsStatic: false } or { IsExtensionMethod: true }
&& i.Expression is not MemberAccessExpressionSyntax;
});
if (nonMemberInvocations.Any())
ReportError("Non-member-access invocations are not supported in precompiled queries"); Prevention
- Avoid casts immediately before method calls inside precompiled query lambdas.
- Replace delegate invocations (myFunc(x)) with direct named method calls.
- Extract intermediate results into separate variables rather than using parenthesized casts inline.
- Keep method chains simple: receiver.Method().OtherMethod() with no casts in between.
When it happens
Trigger: Calling a method through a cast or parenthesized expression that is not a direct member access: `((MyType)obj).Method()`, `((Func<int,int>)del)(5)` (delegate invocation), conditional access chains, or invoking a method on a parenthesized lambda result. Any invocation.Expression that is not a MemberAccessExpressionSyntax with a sub-expression triggers this.
Common situations: Developers who cast query sources or intermediate results inline, or who invoke delegates/groups directly. Common in complex projections where the developer casts an anonymous-typed intermediate or calls a method on a boxed/unboxed value. Also seen when using method group conversions inside query pipelines.
Related errors
- Could not find symbol for method invocation
- MemberAccess: couldn't find member
- MemberAccess: Couldn't find symbol for member
- MemberAccess on multi-dimensional array
- ArrayCreation: multi-dimensional array
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/6c55127e5b2a9d01.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:563
throw new InvalidOperationException("Could not find symbol for method invocation: " + invocation);
}
// First, if the method return type is the user's DbContext type (e.g. DbContext local variable, or field/property), return a
// constant over that DbContext type; the invocation can serve as the root for a LINQ query we can precompile.
if (methodSymbol.ReturnType.Equals(_userDbContextSymbol, SymbolEqualityComparer.Default))
{
return Constant(_userDbContext);
}
var declaringType = ResolveType(methodSymbol.ContainingType);
Expression? instance = null;
if (!methodSymbol.IsStatic || methodSymbol.IsExtensionMethod)
{
// In normal method calls (the ones we support), the invocation node is composed on top of a member access
if (invocation.Expression is not MemberAccessExpressionSyntax { Expression: var receiver })
{
throw new NotSupportedException($"Invocation over non-member access: {invocation}");
}
instance = Visit(receiver);
}
MethodInfo? methodInfo;
if (methodSymbol.IsGenericMethod)
{
var originalDefinition = methodSymbol.OriginalDefinition;
if (originalDefinition.ReducedFrom is not null)
{
originalDefinition = originalDefinition.ReducedFrom;
}
// To accurately find the right open generic method definition based on the Roslyn symbol, we need to create a mapping between
// generic type parameter names (based on the Roslyn side) and .NET reflection Types representing those type parameters.
// This includes both type parameters immediately on the generic method, as well as type parameters from the method'sView on GitHub (pinned to 3a2006ef56)