dotnet/efcore · error · NotImplementedException
Power over non-double operands
Error message
Power over non-double operands
What it means
Thrown by LinqToCSharpSyntaxTranslator.VisitBinary when an ExpressionType.Power binary is encountered whose operands are not both System.Double. Power over double is lowered to a call to Math.Pow(double,double); any other operand type (int, decimal, float, etc.) is unhandled and produces this NotImplementedException.
Solutions
- Cast both operands of Expression.Power to double before constructing the Power node, and cast the result back if needed.
- Replace Expression.Power with an explicit Expression.Call(typeof(Math), nameof(Math.Pow), null, leftAsDouble, rightAsDouble).
- If the integer/decimal power semantics are required, compute the value outside the expression tree and inline the result as a constant.
Example fix
// before
var power = Expression.Power(
Expression.Constant(2),
Expression.Constant(10)); // both int -> throws
// after
var power = Expression.Power(
Expression.Convert(Expression.Constant(2), typeof(double)),
Expression.Convert(Expression.Constant(10), typeof(double))); Defensive patterns
Strategy: validation
Validate before calling
// Reject non-double Power operands before translating to C#.
using System.Linq.Expressions;
bool IsSupportedPower(BinaryExpression b)
=> b.NodeType == ExpressionType.Power
&& b.Left.Type == typeof(double)
&& b.Right.Type == typeof(double);
// In a visitor, ensure all Power nodes are double-typed before handing the tree off. Type guard
static bool IsDoublePower(BinaryExpression b)
=> b.NodeType == ExpressionType.Power
&& b.Left.Type == typeof(double)
&& b.Right.Type == typeof(double); Prevention
- Always convert Power operands to double before constructing Expression.Power.
- If you need integer/decimal exponentiation, compute the value out-of-band and inline the result.
- Add a pre-translation visitor that asserts every Power node has double operands.
When it happens
Trigger: An expression tree handed to LinqToCSharpSyntaxTranslator contains an Expression.Power node whose Left.Type or Right.Type is not double — e.g. an int power built via Expression.Power(Expression.Constant(2), Expression.Constant(3)), or a decimal power.
Common situations: A query-translation extension or a manually-built expression tree uses Expression.Power over integer/decimal operands and then feeds the result to the C# syntax translator (compiled-query source generation); EF provider extensions that materialize Power expressions for non-double numerics.
Related errors
- BinaryExpression with
- DebugInfo nodes are not supporting when translating…
- Encountered a constant of unsupported type
- IndexExpression with multiple arguments
- The same ParameterExpression instance with name
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/8171278b9ebd1cf9.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:337
case ExpressionType.OrAssign:
return VisitAssignment(binary, SyntaxKind.OrAssignmentExpression);
case ExpressionType.LeftShiftAssign:
return VisitAssignment(binary, SyntaxKind.LeftShiftAssignmentExpression);
case ExpressionType.RightShiftAssign:
return VisitAssignment(binary, SyntaxKind.RightShiftAssignmentExpression);
case ExpressionType.ExclusiveOrAssign:
return VisitAssignment(binary, SyntaxKind.ExclusiveOrAssignmentExpression);
case ExpressionType.Power when binary.Left.Type == typeof(double) && binary.Right.Type == typeof(double):
return Visit(
Expression.Call(
_mathPowMethod ??= typeof(Math).GetMethod(
nameof(Math.Pow), BindingFlags.Static | BindingFlags.Public, [typeof(double), typeof(double)])!,
binary.Left,
binary.Right));
case ExpressionType.Power:
throw new NotImplementedException("Power over non-double operands");
case ExpressionType.PowerAssign:
return Visit(
Expression.Assign(
binary.Left,
Expression.Power(
binary.Left,
binary.Right)));
}
var liftedStatementOrigPosition = _liftedState.Statements.Count;
var left = Translate<ExpressionSyntax>(binary.Left);
var liftedStatementLeftPosition = _liftedState.Statements.Count;
var right = Translate<ExpressionSyntax>(binary.Right);
// If both sides were lifted, we don't need to do anything special. Same if the left side was lifted.
// But if the right side was lifted and the left wasn't, then in order to preserve evaluation order we need to lift the left side
// out as well, otherwise the right side gets evaluated before the left.View on GitHub (pinned to 3a2006ef56)