dotnet/efcore · error · NotSupportedException

Unsupported syntax node of type '{node.GetType()}': {node}

Error message

Unsupported syntax node of type '{node.GetType()}': {node}

What it means

DefaultVisit is the catch-all that throws NotSupportedException for any C# syntax node type lacking a specific Visit* override. It is the generic 'this C# construct is not supported in precompiled queries' error; the node type in the message identifies the offending construct.

Source

Thrown at src/EFCore.Design/Query/Internal/CSharpToLinqTranslator.cs:1026

    {
        if (_semanticModel.GetSymbolInfo(typeOf.Type).Symbol is not ITypeSymbol typeSymbol)
        {
            throw new InvalidOperationException(
                "Could not find symbol for typeof() expression: " + typeOf);
        }

        var type = ResolveType(typeSymbol);
        return Constant(type, typeof(Type));
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public override Expression DefaultVisit(SyntaxNode node)
        => throw new NotSupportedException($"Unsupported syntax node of type '{node.GetType()}': {node}");

    private Expression VisitLambdaExpression(AnonymousFunctionExpressionSyntax lambda, Type? expectedType = null)
    {
        if (lambda.ExpressionBody is null)
        {
            throw new NotSupportedException("Lambda with null expression body");
        }

        if (lambda.Modifiers.Any())
        {
            throw new NotSupportedException("Lambda with modifiers not supported: " + lambda.Modifiers);
        }

        if (!lambda.AsyncKeyword.IsKind(SyntaxKind.None))
        {
            throw new NotSupportedException("Async lambdas are not supported");
        }

View on GitHub (pinned to dbf9771522)

Solutions

  1. Identify the unsupported construct from the node type printed in the message
  2. Rewrite using simpler expression-based constructs that map to expression trees
  3. Hoist unsupported logic out of the query into a captured local computed beforehand

Example fix

// before (switch expression, unsupported)
var q = ctx.Items.Select(i => i.Kind switch { 1 => "a", _ => "b" });
// after (ternary, supported)
var q = ctx.Items.Select(i => i.Kind == 1 ? "a" : "b");
Defensive patterns

Strategy: validation

Validate before calling

// Scan precompiled query source for constructs the translator cannot visit.
// Flag: switch expressions, pattern matching 'is', null-conditional '?.', statement-bodied lambdas,
// lock/using/checked blocks, tuple expressions.
static bool UsesUnsupported(string src) =>
    System.Text.RegularExpressions.Regex.IsMatch(src, @"switch\s*\{|\bis\s+\w+\s+\w+|\?\.|=>\s*\{");
if (UsesUnsupported(querySource)) { /* rewrite to expression-tree-friendly form */ }

Prevention

When it happens

Trigger: Using a C# construct the translator has no visitor for: statement-bodied lambdas, lock/using/checked/unchecked blocks, switch expressions, pattern-matching 'is', tuple expressions, null-conditional ?., query continuations (into), etc.

Common situations: Writing modern/advanced C# (pattern matching, switch expressions, null-conditional operators) or statement-style code inside a query that gets precompiled.

Related errors


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