dotnet/efcore · error · NotSupportedException

Can't translate method

Error message

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

What it means

Thrown by LinqToCSharpSyntaxTranslator.VisitMethodCall when call.Method.DeclaringType is null. Reflection's MethodBase.DeclaringType is null only for global methods (and a few exotic cases); the translator needs a declaring type to render either a static receiver or an instance receiver expression, so a method with no declaring type cannot be translated.

Solutions

  1. Identify where the null-DeclaringType MethodInfo came from (DynamicMethod, reflection emit) and replace it with a normal MethodInfo on a real type.
  2. Wrap the call so the target method is a static/instance method on a concrete type whose DeclaringType is non-null.
  3. If the call truly is a global method, host it as a static method on a helper type and rewrite the tree to call that.

Example fix

// before — DynamicMethod with no declaring type inserted into a tree
DynamicMethod dm = new("Foo", typeof(int), new[] { typeof(int) });
// ... emit IL ...
var call = Expression.Call(dm.GetMethodInfo(), arg);

// after — host the same logic as a static method on a real type
public static class Helpers { public static int Foo(int x) => /* ... */; }
var call = Expression.Call(
    typeof(Helpers), nameof(Helpers.Foo), null, arg);
Defensive patterns

Strategy: validation

Validate before calling

// Reject MethodCallExpressions whose method has no declaring type.
using System.Linq.Expressions;
using System.Reflection;

bool HasNoDeclaringTypeCall(Expression e)
{
    bool bad = false;
    new CallChecker(c => { if (c.Method.DeclaringType is null) bad = true; }).Visit(e);
    return bad;
}

class CallChecker(Action<MethodCallExpression> onCall) : ExpressionVisitor
{
    protected override Expression VisitMethodCall(MethodCallExpression c) { onCall(c); return base.VisitMethodCall(c); }
}

Type guard

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

Prevention

When it happens

Trigger: An expression tree invokes a method whose MethodInfo reports a null DeclaringType — global-scope methods from dynamic assemblies, certain DynamicMethod bindings, or hand-crafted DynamicMethod-based MethodInfos inserted into a tree.

Common situations: DynamicMethod or other reflection-emit scenarios where MethodInfo.DeclaringType is null; building expression trees around global functions; malformed MethodInfo wrappers from third-party IL emit libraries.

Related errors


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

Appendix: 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 3a2006ef56)