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

  1. 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();`
  2. Replace delegate invocations with direct method calls that Roslyn can resolve as member accesses.
  3. Avoid parenthesized casts immediately before method calls inside precompiled query lambdas — break them into steps.
  4. 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

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


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's

View on GitHub (pinned to 3a2006ef56)