dotnet/efcore · error · NotSupportedException

Encountered non-quotable expression of type {node.GetType()}

Error message

Encountered non-quotable expression of type {node.GetType()} when translating expression tree to C#

What it means

Thrown by the expression-tree-to-C# translator (LinqToCSharpSyntaxTranslator.VisitExtension, line 2691) that backs EF Core's precompiled-query feature. It only knows how to render EntityQueryRootExpression nodes back into C#; any other extension Expression node type it cannot quote into source code causes this NotSupportedException. It surfaces as a query precompilation failure when generating the C# interceptor source for a query whose tree contains a node the translator was never taught to handle.

Source

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

    /// <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>
    protected override Expression VisitExtension(Expression node)
    {
        // TODO: Remove any EF-specific code from this visitor (extend if needed)
        // TODO: Hack mode. Visit the expression beforehand to replace EntityQueryRootExpression with context.Set<>(), or receive it in this visitor as a replacement or something.
        if (node is EntityQueryRootExpression entityQueryRoot)
        {
            // TODO: STET
            Result = ParseExpression($"context.Set<{entityQueryRoot.EntityType.ClrType.Name}>()");
            return node;
        }

        throw new NotSupportedException(
            $"Encountered non-quotable expression of type {node.GetType()} when translating expression tree to C#");
    }

    private ArgumentSyntax[] TranslateMethodArguments(ParameterInfo[] parameters, IReadOnlyList<Expression> arguments)
    {
        var translatedExpressions = TranslateList(arguments);
        var translatedArguments = new ArgumentSyntax[arguments.Count];

        for (var i = 0; i < translatedExpressions.Length; i++)
        {
            var parameter = parameters[i];
            var argument = Argument(translatedExpressions[i]);

            if (parameter.IsOut)
            {
                argument = argument.WithRefKindKeyword(Token(SyntaxKind.OutKeyword));
            }
            else if (parameter.IsIn)

View on GitHub (pinned to dbf9771522)

Solutions

  1. Remove or simplify the part of the LINQ query that introduces the unsupported expression node (e.g. drop the custom extension/operator causing the non-EF node) so the tree only contains standard EF nodes.
  2. Exclude the offending query from precompiled-query generation and let it run through the normal EF query pipeline instead.
  3. Upgrade EF Core to a version that recognises the expression node type shown in the message (the type name is printed via node.GetType()).
  4. If you control the expression, avoid injecting custom extension nodes into queries you intend to precompile; keep those queries to standard LINQ/EF operators.

Example fix

// before: a query using a custom extension that injects a non-EF expression node
var q = db.Blogs.Where(b => b.Id > 0).UseMyCustomOperator();

// after: drop the unsupported operator for the query being precompiled
var q = db.Blogs.Where(b => b.Id > 0);
Defensive patterns

Strategy: try-catch

Validate before calling

// Before precompiling, sanity-check the query tree for non-EF extension nodes
static bool HasOnlyKnownRoots(Expression e) => e is not Expression
    || e is EntityQueryRootExpression
    || e.NodeType != ExpressionType.Extension;

// (Best validated by precompiling a query in isolation first; if it fails, simplify it.)

Type guard

static bool IsSupportedQueryRoot(Expression e)
    => e is EntityQueryRootExpression || e.NodeType != ExpressionType.Extension;

Try / catch

// Precompiled-query pipelines collect failures; if invoking directly, catch NotSupportedException
try
{
    // run precompiled-query generation for the query
}
catch (NotSupportedException ex) when (ex.Message.Contains("non-quotable expression"))
{
    // log the query, exclude it from precompilation, fall back to normal execution
}

Prevention

When it happens

Trigger: Running precompiled query generation ('dotnet ef dbcontext optimize' with precompiled queries, or the PrecompiledQueryCodeGenerator pipeline) over a LINQ query whose parsed expression tree contains a non-EF extension Expression node that is not an EntityQueryRootExpression. VisitExtension's single handled case is EntityQueryRootExpression; everything else hits the throw.

Common situations: Using a third-party or custom Expression-derived node in a query (e.g. a provider-specific query root, a custom SQL/FromSql expression node, or an extension injected by another EF extension library). Hitting an EF Core version where a newly added query-root type is not yet recognised by the translator. Mixing EF extensions that emit proprietary expression nodes into a query targeted for precompilation.

Related errors


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