{"record":{"id":"f33251b1d5c66a07","repo":"vitessio/vitess","slug":"invalid-comparison-operator","errorCode":null,"errorMessage":"invalid comparison operator","messagePattern":"invalid comparison operator","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/evalengine/expr_compare.go","lineNumber":350,"sourceCode":"\t\tc.asm.CmpTuple(c.env.CollationEnv(), true)\n\t\tc.asm.Cmp_eq_n()\n\tcase compareNE:\n\t\tc.asm.CmpTuple(c.env.CollationEnv(), true)\n\t\tc.asm.Cmp_ne_n()\n\tcase compareLT:\n\t\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\t\tc.asm.Cmp_lt_n()\n\tcase compareLE:\n\t\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\t\tc.asm.Cmp_le_n()\n\tcase compareGT:\n\t\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\t\tc.asm.Cmp_gt_n()\n\tcase compareGE:\n\t\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\t\tc.asm.Cmp_ge_n()\n\tdefault:\n\t\tpanic(\"invalid comparison operator\")\n\t}\n\treturn ctype{Type: sqltypes.Int64, Flag: flagNullable | flagIsBoolean, Col: collationNumeric}, nil\n}\n\nfunc (expr *ComparisonExpr) compile(c *compiler) (ctype, error) {\n\tlt, err := expr.Left.compile(c)\n\tif err != nil {\n\t\treturn ctype{}, err\n\t}\n\n\tvar skip1 *jump\n\tswitch expr.Op.(type) {\n\tcase compareNullSafeEQ:\n\tdefault:\n\t\tskip1 = c.compileNullCheck1(lt)\n\t}\n\n\trt, err := expr.Right.compile(c)","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/expr_compare.go#L332-L368","documentation":"The tuple-comparison compiler (compileAsTuple) switches over the ComparisonExpr's operator and only supports EQ/NE/LT/LE/GT/GE-style tuple comparisons it knows about. An operator enum value outside the handled set reaches the default branch and panics. This is an internal exhaustive-switch guard: sqlparser/IR should never produce a comparison operator that lacks a tuple compilation strategy.","triggerScenarios":"Compiling a ComparisonExpr with a comparison operator value not in the switch's cases while the compiler has chosen the tuple-comparison path (both operands are tuples). Typically only possible with a corrupted/extended operator enum or a new operator added without tuple support.","commonSituations":"Adding a new comparison operator to the IR without implementing compileAsTuple support; tests constructing ComparisonExpr with invalid operator constants; inconsistent generated code between parser and evalengine.","solutions":["Check which operator value hit the default branch and confirm it is valid for tuple comparison","Add a case for the missing operator in compileAsTuple with the appropriate CmpTuple asm sequence","Reject non-tuple-comparable operators earlier during typecheck so they fail with a proper error","Rebuild generated IR code to ensure parser and compiler agree on operator values"],"exampleFix":"// before\ncase compareGE:\n\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\tc.asm.Cmp_ge_n()\ndefault:\n\tpanic(\"invalid comparison operator\")\n// after\ncase compareGE:\n\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\tc.asm.Cmp_ge_n()\ncase compareNewOp:\n\tc.asm.CmpTuple(c.env.CollationEnv(), false)\n\tc.asm.Cmp_newop_n()\ndefault:\n\tpanic(\"invalid comparison operator\")","handlingStrategy":"validation","validationCode":"// Validate the comparison operator is one supported for tuples\nfunc tupleComparable(op evalengine.ComparisonOp) bool {\n\tswitch op {\n\tcase evalengine.Equal, evalengine.NotEqual, evalengine.LessThan,\n\t\tevalengine.LessEqual, evalengine.GreaterThan, evalengine.GreaterEqual:\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":"func isTupleComparison(expr *evalengine.ComparisonExpr) (supported bool) {\n\t_, lTuple := expr.Left.(evalengine.TupleExpr)\n\t_, rTuple := expr.Right.(evalengine.TupleExpr)\n\treturn lTuple && rTuple && tupleComparable(expr.Operator)\n}","tryCatchPattern":"func safeCompileCompare(expr *evalengine.ComparisonExpr, c *compiler) (ct ctype, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"compare compile panic: %v\", r)\n\t\t}\n\t}()\n\treturn expr.compile(c)\n}","preventionTips":["Only use standard SQL comparison operators in tuple comparisons","Add a compile case whenever adding a new ComparisonOp","Use exhaustive switch linting on operator switches","Pin parser and evalengine to the same build"],"tags":["evalengine","panic","comparison-operator","tuple"],"backgroundTag":"unhandled-switch-case-panic","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}