dotnet/efcore · error · ArgumentOutOfRangeException

BinaryExpression with {binary.NodeType}

Error message

BinaryExpression with {binary.NodeType}

What it means

Thrown by LinqToCSharpSyntaxTranslator.VisitBinary when the BinaryExpression.NodeType does not match any of the supported ExpressionType cases in the syntax-kind switch (which covers arithmetic, comparison, logical, shift, is/as, coalesce, and assignment operators). Any binary node type outside that set hits the ArgumentOutOfRange fallback.

Source

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

            ExpressionType.LessThanOrEqual => SyntaxKind.LessThanOrEqualExpression,

            ExpressionType.AndAlso => SyntaxKind.LogicalAndExpression,
            ExpressionType.OrElse => SyntaxKind.LogicalOrExpression,
            ExpressionType.AndAssign => SyntaxKind.AndAssignmentExpression,
            ExpressionType.OrAssign => SyntaxKind.OrAssignmentExpression,

            ExpressionType.And => SyntaxKind.BitwiseAndExpression,
            ExpressionType.Or => SyntaxKind.BitwiseOrExpression,
            ExpressionType.ExclusiveOr => SyntaxKind.ExclusiveOrExpression,
            ExpressionType.LeftShift => SyntaxKind.LeftShiftExpression,
            ExpressionType.RightShift => SyntaxKind.RightShiftExpression,
            // TODO UnsignedRightShiftExpression

            ExpressionType.TypeIs => SyntaxKind.IsExpression,
            ExpressionType.TypeAs => SyntaxKind.AsExpression,
            ExpressionType.Coalesce => SyntaxKind.CoalesceExpression,

            _ => throw new ArgumentOutOfRangeException("BinaryExpression with " + binary.NodeType)
        };

        Result = BinaryExpression(syntaxKind, left, right);

        return binary;

        Expression VisitAssignment(BinaryExpression assignment, SyntaxKind kind)
        {
            // Detect assignment where the lvalue is a private field or a property with a private accessor; these are handled via
            // [UnsafeAccessor].
            if (assignment.Left is MemberExpression
                {
                    Member: FieldInfo { IsPublic: false } or PropertyInfo { SetMethod.IsPublic: false }
                } memberExpression)
            {
                TranslateNonPublicMemberAssignment(memberExpression, assignment.Right, kind);

                return assignment;

View on GitHub (pinned to 3a2006ef56)

Solutions

  1. Inspect binary.NodeType in a debugger to identify the unsupported value and rewrite the tree to use a supported equivalent (e.g. express the operation as a method call).
  2. Replace the exotic binary with an equivalent Expression.Call to a method the translator supports.
  3. If this is a newly-introduced standard ExpressionType, file/track an EF Core issue to extend the switch; in the meantime avoid that operator in trees destined for code generation.

Example fix

// before — exotic NodeType reaching VisitBinary
// (e.g. hand-built BinaryExpression with an unsupported NodeType)
var weird = Expression.MakeBinary(
    someCustomNodeType, left, right);

// after — express the same operation as a supported method call
var equivalent = Expression.Call(
    typeof(MyOps), nameof(MyOps.DoOp), null, left, right);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-walk the tree to confirm all binary node types are supported.
using System.Linq.Expressions;

static readonly HashSet<ExpressionType> SupportedBinaryTypes = new()
{
    ExpressionType.Equal, ExpressionType.NotEqual,
    ExpressionType.Add, ExpressionType.AddChecked,
    ExpressionType.Subtract, ExpressionType.SubtractChecked,
    ExpressionType.Multiply, ExpressionType.MultiplyChecked,
    ExpressionType.Divide, ExpressionType.Modulo,
    ExpressionType.GreaterThan, ExpressionType.GreaterThanOrEqual,
    ExpressionType.LessThan, ExpressionType.LessThanOrEqual,
    ExpressionType.AndAlso, ExpressionType.OrElse,
    ExpressionType.AndAssign, ExpressionType.OrAssign,
    ExpressionType.And, ExpressionType.Or,
    ExpressionType.ExclusiveOr, ExpressionType.LeftShift, ExpressionType.RightShift,
    ExpressionType.TypeIs, ExpressionType.TypeAs, ExpressionType.Coalesce,
};

bool AllBinarySupported(Expression e)
{
    bool ok = true;
    new BinaryChecker(b => { if (!SupportedBinaryTypes.Contains(b.NodeType)) ok = false; }).Visit(e);
    return ok;
}

class BinaryChecker(Action<BinaryExpression> onBinary) : ExpressionVisitor
{
    protected override Expression VisitBinary(BinaryExpression b) { onBinary(b); return base.VisitBinary(b); }
}

Prevention

When it happens

Trigger: An expression tree contains a binary node type that the translator has not been taught to render, e.g. ExpressionType.Assign handled elsewhere but a future/new ExpressionType, a user-defined binary operator represented as an exotic NodeType, or an extension node masquerading as a binary.

Common situations: Upgrading to a newer .NET runtime that introduced additional ExpressionType values; third-party expression-tree builders producing non-standard node types; building expression trees by hand with mismatched NodeType vs. operand kinds.

Related errors


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