dotnet/efcore · error · InvalidOperationException
The same ParameterExpression instance with name
Error message
The same ParameterExpression instance with name '{parameter}' was used as a variable declaration in a block and a nested block inside it. This is not allowed - use different ParameterExpression instances. What it means
Thrown by LinqToCSharpSyntaxTranslator.VisitBlock when the same ParameterExpression instance is added as a variable to a non-lifted block scope (the local StackFrame) but it is already registered. LINQ treats ParameterExpression by reference identity; reusing one instance as a variable in both an outer and nested (non-lifted) block produces ambiguous C# because the variable's declaration scope is unclear.
Solutions
- Allocate a fresh ParameterExpression for each block scope that declares the variable; do not reuse instances across sibling/nested declaration scopes.
- If you must share by name, declare the variable once in the outermost block and do not re-declare it in nested blocks.
- Audit tree construction with Expression.Parameter equality-by-reference in mind — equal names do not imply equal identity.
Example fix
// before — same instance reused across nested block scopes
var v = Expression.Variable(typeof(int), "x");
var inner = Expression.Block(
new[] { v },
Expression.Assign(v, Expression.Constant(1)));
var outer = Expression.Block(
new[] { v },
inner,
Expression.Add(v, Expression.Constant(2)));
// after — distinct instances per scope
var vOuter = Expression.Variable(typeof(int), "x");
var vInner = Expression.Variable(typeof(int), "x");
var inner = Expression.Block(
new[] { vInner },
Expression.Assign(vInner, Expression.Constant(1)));
var outer = Expression.Block(
new[] { vOuter },
inner,
Expression.Add(vOuter, Expression.Constant(2))); Defensive patterns
Strategy: validation
Validate before calling
// Verify no ParameterExpression is reused as a variable across nested blocks.
using System.Linq.Expressions;
bool HasSharedVariableInNestedBlocks(Expression e)
{
var stack = new Stack<HashSet<ParameterExpression>>();
bool clash = false;
new NestedBlockVisitor(() => stack, () =>
{
// called when a duplicate is detected
clash = true;
}).Visit(e);
return clash;
}
// A simplified visitor skeleton:
class NestedBlockVisitor : ExpressionVisitor
{
private readonly Stack<HashSet<ParameterExpression>> _scope;
private readonly Action _onClash;
public NestedBlockVisitor(Func<Stack<HashSet<ParameterExpression>>> scope, Action onClash)
{ _scope = scope(); _onClash = onClash; }
protected override Expression VisitBlock(BlockExpression b)
{
var current = new HashSet<ParameterExpression>();
foreach (var v in b.Variables)
if (!current.Add(v)) _onClash();
_scope.Push(current);
var r = base.VisitBlock(b);
_scope.Pop();
return r;
}
} Prevention
- Allocate a fresh ParameterExpression per declaration scope; never share an instance between sibling/nested blocks.
- Remember ParameterExpression equality is by reference, not by Name.
- Use a builder helper that allocates and tracks variables per scope to prevent accidental sharing.
When it happens
Trigger: An expression tree built manually reuses a single ParameterExpression instance in the Variables collection of two nested BlockExpressions that are both rendered as statement scopes (i.e. neither is an expression-context block that gets lifted).
Common situations: Hand-rolled expression-tree builders that share a ParameterExpression across blocks for convenience; refactoring Expression.Variable calls into a shared field; converting imperative code that used the same symbol name into nested blocks.
Related errors
- BinaryExpression with
- Power over non-double operands
- Anonymous type creation without members
- Can't translate method
- Compound assignment of private property not yet supported
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e9205a6561979392.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:516
{
var (variables, variableNames) = (stackFrame.Variables, stackFrame.VariableNames);
var uniquifiedName = UniquifyVariableName(parameter.Name ?? "unnamed");
if (blockContext == ExpressionContext.Expression)
{
if (!_liftedState.Variables.TryAdd(parameter, uniquifiedName))
{
throw new NotSupportedException("Parameter clash during expression lifting for: " + parameter.Name);
}
_liftedState.VariableNames.Add(uniquifiedName);
}
else
{
if (!variables.TryAdd(parameter, uniquifiedName))
{
throw new InvalidOperationException(
DesignStrings.SameParameterExpressionDeclaredAsVariableInNestedBlocks(parameter.Name ?? "<null>"));
}
variableNames.Add(uniquifiedName);
}
}
var unassignedVariables = block.Variables.ToList();
var statements = new List<StatementSyntax>();
LabeledStatementSyntax? pendingLabeledStatement = null;
// Now visit the block's expressions
for (var i = 0; i < block.Expressions.Count; i++)
{
var expression = block.Expressions[i];
var onLastBlockLine = i == block.Expressions.Count - 1;
_onLastLambdaLine = parentOnLastLambdaLine && onLastBlockLine;View on GitHub (pinned to 3a2006ef56)