dotnet/efcore · error · NotSupportedException

Lifted expressions remaining at top-level in expression cont

Error message

Lifted expressions remaining at top-level in expression context

What it means

Thrown at the end of TranslateCore when translating in expression context but _liftedState.Statements.Count > 0. Some sub-expressions needed to be 'lifted' into separate statements (blocks, multi-arm conditionals), but at top-level expression context there is no enclosing statement scope to lift into. Part of EF Core's LINQ-to-C# syntax translation (compiled models / precompiled queries).

Source

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

        try
        {
            Visit(node);
        }
        finally
        {
            if (constantReplacements != null)
            {
                foreach (var name in constantReplacements.Values)
                {
                    rootFrame.VariableNames.Remove(name);
                }
            }
        }

        if (_liftedState.Statements.Count > 0
            && _context == ExpressionContext.Expression)
        {
            throw new NotSupportedException("Lifted expressions remaining at top-level in expression context");
        }

        Check.DebugAssert(_stack.Count == 1, "_parameterStack.Count == 1");
        Check.DebugAssert(_stack.Peek().Variables.Count == 0, "_stack.Peek().Parameters.Count == 0");
        Check.DebugAssert(_stack.Peek().VariableNames.Count == 0, "_stack.Peek().ParameterNames.Count == 0");
        Check.DebugAssert(_stack.Peek().Labels.Count == 0);
        Check.DebugAssert(_stack.Peek().UniqueLabelNames.Count == 0);

        foreach (var unsafeAccessor in _fieldUnsafeAccessors.Values.Concat(_methodUnsafeAccessors.Values))
        {
            unsafeAccessors.Add(unsafeAccessor);
        }

        return Result!;
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to

View on GitHub (pinned to dbf9771522)

Solutions

  1. Use TranslateStatement instead of TranslateExpression if the expression contains blocks or other constructs requiring lifting.
  2. Simplify the expression to avoid constructs that require lifting.
Defensive patterns

Strategy: validation

Validate before calling

// Choose the right translation entry point based on whether lifting is needed
var needsStatements = ContainsBlockOrLiftableConstruct(node);
var result = needsStatements
    ? translator.TranslateStatement(node, replacements, namespaces, accessors)
    : translator.TranslateExpression(node, replacements, namespaces, accessors);

Prevention

When it happens

Trigger: Translating an expression that contains statement-like constructs (blocks, multi-arm conditionals) at the top level via TranslateExpression rather than TranslateStatement.

Common situations: Calling TranslateExpression on an expression tree that actually requires statement-form translation; expression tree shapes the translator did not expect at top level; internal API misuse.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/8872763c4f7b6327. Report an issue: GitHub.