{"record":{"id":"7f56d8418b37f53e","repo":"dotnet/efcore","slug":"encountered-a-constant-of-unsupported-type-value","errorCode":null,"errorMessage":"Encountered a constant of unsupported type '{value.GetType().Name}'. Only primitive constant nodes are supported.","messagePattern":"Encountered a constant of unsupported type '(.+?)'\\. Only primitive constant nodes are supported\\.","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs","lineNumber":1188,"sourceCode":"        }\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    protected virtual ExpressionSyntax GenerateUnknownValue(object value)\n    {\n        var type = value.GetType();\n        return type.IsValueType\n            && value.Equals(type.GetDefaultValue())\n                ? DefaultExpression(Generate(type))\n                : value is IRelationalQuotableExpression relationalQuotableExpression\n                && Translate(relationalQuotableExpression.Quote()) is ExpressionSyntax expressionSyntax\n                    ? expressionSyntax\n                    : throw new NotSupportedException(\n                        $\"Encountered a constant of unsupported type '{value.GetType().Name}'. Only primitive constant nodes are supported.\"\n                        + Environment.NewLine\n                        + value);\n    }\n\n    /// <inheritdoc />\n    protected override Expression VisitDebugInfo(DebugInfoExpression node)\n        => throw new NotSupportedException(\"DebugInfo nodes are not supporting when translating expression trees to C#\");\n\n    /// <inheritdoc />\n    protected override Expression VisitDefault(DefaultExpression node)\n    {\n        Result = DefaultExpression(Generate(node.Type));\n\n        return node;\n    }\n\n    /// <inheritdoc />","sourceCodeStart":1170,"sourceCodeEnd":1206,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs#L1170-L1206","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before — complex object captured as a constant\nvar settings = new QuerySettings { Threshold = 10 };\nvar pred = Expression.Lambda(\n    Expression.GreaterThan(\n        Expression.Property(param, \"Score\"),\n        Expression.Constant(settings.Threshold)));\n// (GenerateValue hits the fallback if 'settings' itself is the constant)\n\n// after — pass a constant replacement mapping the object to a variable name\nvar replacements = new Dictionary<object, string>\n{\n    { settings, \"settings\" }\n};\ntranslator.TranslateExpression(\n    pred.Body, replacements, namespaces, unsafeAccessors);","handlingStrategy":"validation","validationCode":"// Pre-scan constants and require either a replacement mapping or a supported kind.\nusing System.Linq.Expressions;\nusing System.Collections;\nusing System.Globalization;\nusing System.Text;\n\nbool AllConstantsSupported(Expression e, IReadOnlyDictionary<object, string>? replacements)\n{\n    bool ok = true;\n    new ConstantChecker(c =>\n    {\n        if (c.Value is null) return;\n        if (replacements is not null && replacements.ContainsKey(c.Value)) return;\n        switch (c.Value)\n        {\n            case int or long or uint or ulong or short or sbyte or ushort or byte\n                 or double or float or decimal or char or string or bool:\n            case Enum:\n            case Type:\n            case Guid:\n            case ITuple:\n            case ReferenceEqualityComparer:\n            case CultureInfo:\n            case Encoding:\n                return;\n            default:\n                ok = false;\n                break;\n        }\n    }).Visit(e);\n    return ok;\n}\n\nclass ConstantChecker(Action<ConstantExpression> onConstant) : ExpressionVisitor\n{\n    protected override Expression VisitConstant(ConstantExpression c) { onConstant(c); return base.VisitConstant(c); }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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."],"tags":["ef-core","expression-trees","constants","code-generation","closures","csharp"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}