dotnet/efcore · error · NotSupportedException

DebugInfo nodes are not supporting when translating…

Error message

DebugInfo nodes are not supporting when translating expression trees to C#

What it means

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.

Solutions

  1. Strip DebugInfoExpression nodes before translation using an ExpressionVisitor that removes them (return the inner/next node, or just skip).
  2. Compile the tree without DebugInfoGenerator so no DebugInfoExpression is inserted.
  3. Avoid passing trees that came from a debug-enabled Expression.Compile to this translator.

Example fix

// before — debug info nodes are present in the tree
var tree = Expression.Lambda<Func<int, bool>>(
    Expression.AndAlso(
        new DebugInfoExpression(...),
        Expression.Equal(param, Expression.Constant(1))));
translator.TranslateExpression(tree.Body, ...);

// after — strip debug-info nodes first
var cleaned = new DebugInfoStripper().Visit(tree);
translator.TranslateExpression(cleaned.Body, ...);

class DebugInfoStripper : ExpressionVisitor {
    protected override Expression VisitDebugInfo(DebugInfoExpression node)
        => Expression.Constant(true); // or otherwise neutralize
}
Defensive patterns

Strategy: validation

Validate before calling

// Strip DebugInfoExpression nodes before translation.
using System.Linq.Expressions;

class DebugInfoStripper : ExpressionVisitor
{
    protected override Expression VisitDebugInfo(DebugInfoExpression node)
        => Expression.Constant(true); // neutral placeholder; adjust per tree
}

Expression sanitized = new DebugInfoStripper().Visit(tree);
translator.TranslateExpression(sanitized, ...);

Type guard

static bool ContainsDebugInfo(Expression e)
{
    bool found = false;
    new DebugInfoChecker(() => found = true).Visit(e);
    return found;
}

class DebugInfoChecker(Action> onFound) : ExpressionVisitor
{
    protected override Expression VisitDebugInfo(DebugInfoExpression node) { onFound(); return base.VisitDebugInfo(node); }
}

Prevention

When it happens

Trigger: An expression tree produced with DebugInfoGenerator.MarkEditAndContinue (or a similar debug-info emitter) is handed to LinqToCSharpSyntaxTranslator, which visits the DebugInfoExpression node.

Common situations: 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.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/74f7fd803804ea29. Report an issue: GitHub.

Appendix: source

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

    /// </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 />
    protected override Expression VisitGoto(GotoExpression gotoNode)
    {
        Result = GotoStatement(SyntaxKind.GotoStatement, TranslateLabelTarget(gotoNode.Target));
        return gotoNode;
    }

    /// <inheritdoc />
    protected override Expression VisitInvocation(InvocationExpression invocation)

View on GitHub (pinned to 3a2006ef56)