dotnet/efcore · error · NotSupportedException

Can't translate method '{call.Method.Name}' which has no dec

Error message

Can't translate method '{call.Method.Name}' which has no declaring type

What it means

VisitMethodCall requires call.Method.DeclaringType to be non-null because it must render a qualified reference (DeclaringType.MethodName(...)). A method with no declaring type cannot be turned into valid C#, so the translator throws NotSupportedException. Normal C# method calls always have a declaring type, so this signals a dynamically constructed or special-name method.

Source

Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:1930

        }

        Result =
            ElementAccessExpression(Translate<ExpressionSyntax>(index.Object!))
                .WithArgumentList(
                    BracketedArgumentList(
                        SingletonSeparatedList(
                            Argument(
                                Translate<ExpressionSyntax>(index.Arguments.Single())))));

        return index;
    }

    /// <inheritdoc />
    protected override Expression VisitMethodCall(MethodCallExpression call)
    {
        if (call.Method.DeclaringType is null)
        {
            throw new NotSupportedException($"Can't translate method '{call.Method.Name}' which has no declaring type");
        }

        using var _ = ChangeContext(ExpressionContext.Expression);

        var arguments = TranslateMethodArguments(call.Method.GetParameters(), call.Arguments);

        // For generic methods, we check whether the generic type arguments are inferrable (e.g. they all appear in the parameters), and
        // only explicitly specify the arguments if not. Note that this isn't just for prettier code: anonymous types cannot be explicitly
        // named in code.
        SimpleNameSyntax methodIdentifier;
        if (!call.Method.IsGenericMethod || GenericTypeParameterAreInferrable())
        {
            methodIdentifier = IdentifierName(call.Method.Name);
        }
        else
        {
            Check.DebugAssert(
                call.Method.GetGenericArguments().All(ga => !ga.IsAnonymousType()),

View on GitHub (pinned to dbf9771522)

Solutions

  1. Ensure the called MethodInfo belongs to a real type (call a normal instance or static method with a proper DeclaringType).
  2. Avoid dynamic-method construction inside precompiled queries.
  3. Wrap the operation in a helper method on a concrete type and call that instead.

Example fix

// before: MethodInfo with null DeclaringType
var call = Expression.Call(methodInfoWithoutType, args);
// after: call a normal method on a real type
var call = Expression.Call(typeof(Helper), nameof(Helper.Do), Type.EmptyTypes, args);
Defensive patterns

Strategy: try-catch

Validate before calling

foreach (var call in MethodCallExtractor.From(lambda.Body)) {
    if (call.Method.DeclaringType is null)
        throw new InvalidOperationException($"Method {call.Method.Name} has no declaring type.");
}

Type guard

static bool HasDeclaringType(MethodCallExpression c) => c.Method.DeclaringType is not null;

Try / catch

try { translator.Translate(lambda); }
catch (NotSupportedException ex) when (ex.Message.Contains("no declaring type")) {
    // rewrite the call onto a method with a real owning type, then retranslate
}

Prevention

When it happens

Trigger: A MethodCallExpression whose Method.DeclaringType is null — e.g. a reflection-built or dynamically assembled MethodInfo without an owning type, or certain global/special methods.

Common situations: Hand-constructed expression trees using DynamicMethod or reflection-built MethodInfos; rarely from normal compiled lambdas.

Related errors


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