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
- 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.
- Exclude the offending query from precompiled-query generation and let it run through the normal EF query pipeline instead.
- Upgrade EF Core to a version that recognises the expression node type shown in the message (the type name is printed via node.GetType()).
- 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
- Keep precompiled queries limited to standard LINQ + EF operators; avoid injecting custom extension expression nodes.
- Precompile queries incrementally to catch unsupported nodes early.
- Track the set of EF expression types your queries depend on.
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
- Couldn't find method symbol for: {memberAccessSyntax}
- Couldn't get interceptable location for: '{node}'.
- Generic method on generic type not supported
- Non-extension static method not supported
- The 'setPropertyCalls' argument to 'ExecuteUpdate' may only
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/61187ff70779a3b6.
Report an issue: GitHub.