{"record":{"id":"74f7fd803804ea29","repo":"dotnet/efcore","slug":"debuginfo-nodes-are-not-supporting-when-translatin","errorCode":null,"errorMessage":"DebugInfo nodes are not supporting when translating expression trees to C#","messagePattern":"DebugInfo nodes are not supporting when translating expression trees to C#","errorType":"exception","errorClass":"NotSupportedException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs","lineNumber":1196,"sourceCode":"    /// </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 />\n    protected override Expression VisitGoto(GotoExpression gotoNode)\n    {\n        Result = GotoStatement(SyntaxKind.GotoStatement, TranslateLabelTarget(gotoNode.Target));\n        return gotoNode;\n    }\n\n    /// <inheritdoc />\n    protected override Expression VisitInvocation(InvocationExpression invocation)","sourceCodeStart":1178,"sourceCodeEnd":1214,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs#L1178-L1214","documentation":"Thrown by LinqToCSharpSyntaxTranslator.VisitDebugInfo whenever an incoming expression tree contains a DebugInfoExpression. DebugInfo nodes carry source-file/line markers emitted by the debug expression-tree generator and have no C# source equivalent, so the translator refuses to render them.","triggerScenarios":"An expression tree produced with DebugInfoGenerator.MarkEditAndContinue (or a similar debug-info emitter) is handed to LinqToCSharpSyntaxTranslator, which visits the DebugInfoExpression node.","commonSituations":"Tooling that compiles lambdas with debug info (Expression.Compile with DebugInfoGenerator) and then attempts to round-trip the tree back to C# source; serialization pipelines that retain DebugInfoExpression nodes.","solutions":["Strip DebugInfoExpression nodes before translation using an ExpressionVisitor that removes them (return the inner/next node, or just skip).","Compile the tree without DebugInfoGenerator so no DebugInfoExpression is inserted.","Avoid passing trees that came from a debug-enabled Expression.Compile to this translator."],"exampleFix":"// before — debug info nodes are present in the tree\nvar tree = Expression.Lambda<Func<int, bool>>(\n    Expression.AndAlso(\n        new DebugInfoExpression(...),\n        Expression.Equal(param, Expression.Constant(1))));\ntranslator.TranslateExpression(tree.Body, ...);\n\n// after — strip debug-info nodes first\nvar cleaned = new DebugInfoStripper().Visit(tree);\ntranslator.TranslateExpression(cleaned.Body, ...);\n\nclass DebugInfoStripper : ExpressionVisitor {\n    protected override Expression VisitDebugInfo(DebugInfoExpression node)\n        => Expression.Constant(true); // or otherwise neutralize\n}","handlingStrategy":"validation","validationCode":"// Strip DebugInfoExpression nodes before translation.\nusing System.Linq.Expressions;\n\nclass DebugInfoStripper : ExpressionVisitor\n{\n    protected override Expression VisitDebugInfo(DebugInfoExpression node)\n        => Expression.Constant(true); // neutral placeholder; adjust per tree\n}\n\nExpression sanitized = new DebugInfoStripper().Visit(tree);\ntranslator.TranslateExpression(sanitized, ...);","typeGuard":"static bool ContainsDebugInfo(Expression e)\n{\n    bool found = false;\n    new DebugInfoChecker(() => found = true).Visit(e);\n    return found;\n}\n\nclass DebugInfoChecker(Action> onFound) : ExpressionVisitor\n{\n    protected override Expression VisitDebugInfo(DebugInfoExpression node) { onFound(); return base.VisitDebugInfo(node); }\n}","tryCatchPattern":null,"preventionTips":["Do not compile lambdas with DebugInfoGenerator if the tree will be re-rendered to C#.","Run a stripping visitor before translation.","In serialization round-trips, drop DebugInfoExpression nodes rather than preserving them."],"tags":["ef-core","expression-trees","debuginfo","code-generation","csharp"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}