dotnet/efcore · error · NotSupportedException

Unsupported syntax node of type

Error message

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

What it means

Thrown by DefaultVisit — the catch-all override that fires for ANY C# syntax node type that does not have a specific Visit override in the translator. This is the ultimate fallback: if the translator encounters a syntax construct it has no handler for (no VisitXxx override matched), DefaultVisit throws NotSupportedException. The message includes the node's runtime type and its full text for diagnosis.

Solutions

  1. Identify the unsupported construct from the error message (it includes the node type name) and rewrite it using a more basic form the translator handles.
  2. Replace switch expressions/patterns with if-else chains or ternary operators.
  3. Replace conditional access (x?.Y) with explicit null checks (x != null ? x.Y : null).
  4. Replace tuple syntax with anonymous objects or separate variable bindings.
  5. Replace checked/unchecked with unchecked method calls or remove the checked context.
  6. If the construct is essential, exclude the query from precompilation or file an EF Core issue for support.
  7. Check the EF Core release notes — newer versions may have added support for the construct you're using.

Example fix

// before — switch expression (DefaultVisit catch-all)
var query = ctx.Orders.Select(o => o.Status switch {
    Status.Pending => 0,
    Status.Shipped => 1,
    _ => 2
});

// after — conditional expression
var query = ctx.Orders.Select(o =>
    o.Status == Status.Pending ? 0 :
    o.Status == Status.Shipped ? 1 : 2);
Defensive patterns

Strategy: validation

Validate before calling

// Before precompiling, identify syntax node types that will hit DefaultVisit
var knownOverrides = new HashSet<string> {
    nameof(CSharpSyntaxVisitor<Expression>.VisitBinaryExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitInvocationExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitMemberAccessExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitObjectCreationExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitSimpleLambdaExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitParenthesizedLambdaExpression),
    nameof(CSharpSyntaxVisitor<Expression>.VisitLiteralExpression),
    // ... (all overridden Visit methods in CSharpToLinqTranslator)
};
// Any node whose CSharpSyntaxVisitor dispatches to DefaultVisit will trigger the error
var unhandledNodes = querySyntaxTree.DescendantNodes()
    .Where(n => IsDispatchedToDefaultVisit(n)); // requires knowing the visitor's override set
if (unhandledNodes.Any())
    ReportError($"Unsupported syntax node(s): {string.Join(", ", unhandledNodes.Select(n => n.GetType().Name))}");

Try / catch

// If invoking the translator programmatically:
try { var expr = translator.Translate(node, semanticModel); }
catch (NotSupportedException ex) when (ex.Message.Contains("Unsupported syntax node"))
{
    // Log the unsupported construct and fall back to runtime compilation
    LogPrecompileSkipped(node, ex.Message);
    // The query will compile normally at runtime without precompilation
}

Prevention

When it happens

Trigger: Any C# expression construct not explicitly handled by a Visit override triggers this. Examples include: checked/unchecked expressions, sizeof expressions, stackalloc expressions, default value expressions in some forms, tuple expressions, switch expressions, switch statements, pattern matching (is-pattern), conditional access (?.) in certain positions, range expressions, interpolated string handlers in complex forms, ref expressions, yield expressions, local function declarations, lock/fixed/using statements, and any new C# language feature not yet supported by the translator.

Common situations: Using newer C# language features (C# 10-13+) inside precompiled queries before the translator is updated to support them; using pattern matching (switch expressions, `is` patterns) in query predicates; using tuple deconstruction in projections; using checked arithmetic; using conditional access expressions (`entity?.Property`); using interpolation with complex format providers. The most common trigger is simply writing modern idiomatic C# in a query that gets precompiled.

Related errors


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

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