dotnet/efcore · error · NotSupportedException
Encountered a constant of unsupported type
Error message
Encountered a constant of unsupported type '{value.GetType().Name}'. Only primitive constant nodes are supported. What it means
Thrown by LinqToCSharpSyntaxTranslator.GenerateUnknownValue, which is the fallback arm of GenerateValue when a constant value is not one of the supported kinds (primitives, string, enum, Type, Guid, well-known CultureInfo/Encoding/Comparer singletons, ValueTuple) and is not an IRelationalQuotableExpression that can be quoted. The translator cannot emit a C# literal for arbitrary reference types, so it rejects them.
Solutions
- Pass a constantReplacements dictionary to TranslateExpression/TranslateStatement that maps the captured value to a parameter/variable name the generated code can reference.
- Refactor the query to capture only primitives (ids, strings) and look up the complex object inside the lambda via a parameter instead of a closure.
- If the value type implements IRelationalQuotableExpression, make sure its Quote() returns a translatable expression; otherwise it will still fall through to this throw.
- Replace the captured object with a primitive key and resolve the object from a service inside the lambda.
Example fix
// before — complex object captured as a constant
var settings = new QuerySettings { Threshold = 10 };
var pred = Expression.Lambda(
Expression.GreaterThan(
Expression.Property(param, "Score"),
Expression.Constant(settings.Threshold)));
// (GenerateValue hits the fallback if 'settings' itself is the constant)
// after — pass a constant replacement mapping the object to a variable name
var replacements = new Dictionary<object, string>
{
{ settings, "settings" }
};
translator.TranslateExpression(
pred.Body, replacements, namespaces, unsafeAccessors); Defensive patterns
Strategy: validation
Validate before calling
// Pre-scan constants and require either a replacement mapping or a supported kind.
using System.Linq.Expressions;
using System.Collections;
using System.Globalization;
using System.Text;
bool AllConstantsSupported(Expression e, IReadOnlyDictionary<object, string>? replacements)
{
bool ok = true;
new ConstantChecker(c =>
{
if (c.Value is null) return;
if (replacements is not null && replacements.ContainsKey(c.Value)) return;
switch (c.Value)
{
case int or long or uint or ulong or short or sbyte or ushort or byte
or double or float or decimal or char or string or bool:
case Enum:
case Type:
case Guid:
case ITuple:
case ReferenceEqualityComparer:
case CultureInfo:
case Encoding:
return;
default:
ok = false;
break;
}
}).Visit(e);
return ok;
}
class ConstantChecker(Action<ConstantExpression> onConstant) : ExpressionVisitor
{
protected override Expression VisitConstant(ConstantExpression c) { onConstant(c); return base.VisitConstant(c); }
} Prevention
- Pass a constantReplacements map covering every captured non-primitive object before translating.
- Capture only primitive keys in query lambdas; resolve complex objects inside the lambda via parameters.
- Run a pre-scan visitor to enumerate all ConstantExpression values and confirm each is supported or replaced.
When it happens
Trigger: An expression tree being rendered to C# contains a ConstantExpression whose Value is a complex/custom object (a DTO, a closure class instance, a dictionary, etc.) and no constant replacement was supplied to substitute a variable name for it.
Common situations: Capturing a non-primitive variable in a query (e.g. a settings object, a list, a custom comparer) when generating compiled-query C#; provider extensions that wrap complex state as constants; running LinqToCSharpSyntaxTranslator without constantReplacements for captured closures.
Related errors
- DebugInfo nodes are not supporting when translating…
- IndexExpression with multiple arguments
- Power over non-double operands
- Anonymous type creation without members
- BinaryExpression with
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/7f56d8418b37f53e.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:1188
}
}
/// <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 virtual ExpressionSyntax GenerateUnknownValue(object value)
{
var type = value.GetType();
return type.IsValueType
&& value.Equals(type.GetDefaultValue())
? DefaultExpression(Generate(type))
: value is IRelationalQuotableExpression relationalQuotableExpression
&& Translate(relationalQuotableExpression.Quote()) is ExpressionSyntax expressionSyntax
? expressionSyntax
: throw new NotSupportedException(
$"Encountered a constant of unsupported type '{value.GetType().Name}'. Only primitive constant nodes are supported."
+ Environment.NewLine
+ value);
}
/// <inheritdoc />
protected override Expression VisitDebugInfo(DebugInfoExpression node)
=> throw new NotSupportedException("DebugInfo nodes are not supporting when translating expression trees to C#");
/// <inheritdoc />
protected override Expression VisitDefault(DefaultExpression node)
{
Result = DefaultExpression(Generate(node.Type));
return node;
}
/// <inheritdoc />View on GitHub (pinned to 3a2006ef56)