vitessio/vitess · error

unexpected comparison operator

Error message

unexpected comparison operator

What it means

During comparison-expression compilation, the compiler switches over all comparison operator kinds; the null-safe-equality case (compareNullSafeEQ) is the last handled one, and anything after it hits this panic. It means an unrecognized comparison operator value reached the compiler, breaking the assumption that the typechecker/IR only emits known operators.

Source

Thrown at go/vt/vtgate/evalengine/expr_compare.go:475

	case compareGT:
		if swapped {
			c.asm.Cmp_lt()
		} else {
			c.asm.Cmp_gt()
		}
	case compareGE:
		if swapped {
			c.asm.Cmp_le()
		} else {
			c.asm.Cmp_ge()
		}
	case compareNullSafeEQ:
		c.asm.jumpDestination(skip2)
		c.asm.Cmp_eq()
		return cmptype, nil

	default:
		panic("unexpected comparison operator")
	}

	c.asm.jumpDestination(skip1, skip2)
	return cmptype, nil
}

func evalInExpr(collationEnv *collations.Environment, lhs eval, rhs *evalTuple) (boolean, error) {
	if lhs == nil {
		return boolNULL, nil
	}

	var foundNull, found bool
	for _, rtuple := range rhs.t {
		numeric, isNull, err := evalCompareAll(lhs, rtuple, true, collationEnv)
		if err != nil {
			return boolNULL, err
		}
		if isNull {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Log/inspect the offending operator value to identify the unhandled kind
  2. Add a compile case for the new operator in expr_compare.go
  3. Validate operators at IR-construction time so invalid values fail early with a clear error
  4. Ensure parser and evalengine are built from the same version

Example fix

// before
case compareNullSafeEQ:
	c.asm.jumpDestination(skip2)
	c.asm.Cmp_eq()
	return cmptype, nil
default:
	panic("unexpected comparison operator")
// after
case compareNullSafeEQ:
	c.asm.jumpDestination(skip2)
	c.asm.Cmp_eq()
	return cmptype, nil
case compareNewOp:
	c.asm.jumpDestination(skip2)
	c.asm.Cmp_new()
	return cmptype, nil
default:
	panic("unexpected comparison operator")
Defensive patterns

Strategy: validation

Validate before calling

// Enumerate the valid comparison operators before constructing expressions
var validCompareOps = map[evalengine.ComparisonOp]bool{ /* EQ, NE, LT, LE, GT, GE, NullSafeEQ, ... */ }
func opIsValid(op evalengine.ComparisonOp) bool { return validCompareOps[op] }

Type guard

func isKnownComparisonOp(op evalengine.ComparisonOp) bool {
	return op >= evalengine.Equal && op <= evalengine.NullSafeEqual
}

Try / catch

defer func() {
	if r := recover(); r != nil {
		err = fmt.Errorf("comparison compile panic: %v (operator %v)", r, expr.Operator)
	}
}()

Prevention

When it happens

Trigger: Compiling a ComparisonExpr whose Operator field holds an enum value not covered by the switch (e.g., a newly added operator without a compile case, or an invalid zero/garbage value from a manually constructed IR node).

Common situations: Evalengine development adding new comparison operators; test code constructing ComparisonExpr with wrong constants; version-skew builds where parser emits an operator the compiler does not know.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/eb564ec79ea0e7e5. Report an issue: GitHub.