{"record":{"id":"412938650daf27c0","repo":"vitessio/vitess","slug":"unexpected-arithmetic-operator","errorCode":null,"errorMessage":"unexpected arithmetic operator","messagePattern":"unexpected arithmetic operator","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/evalengine/expr_bit.go","lineNumber":330,"sourceCode":"\n\tc.asm.jumpDestination(skip1, skip2)\n\treturn ctype{Type: sqltypes.Uint64, Flag: nullableFlags(lt.Flag | rt.Flag), Col: collationNumeric}, nil\n}\n\nfunc (expr *BitwiseExpr) compile(c *compiler) (ctype, error) {\n\tswitch expr.Op.(type) {\n\tcase *opBitAnd:\n\t\treturn expr.compileBinary(c, c.asm.BitOp_and_bb, c.asm.BitOp_and_uu)\n\tcase *opBitOr:\n\t\treturn expr.compileBinary(c, c.asm.BitOp_or_bb, c.asm.BitOp_or_uu)\n\tcase *opBitXor:\n\t\treturn expr.compileBinary(c, c.asm.BitOp_xor_bb, c.asm.BitOp_xor_uu)\n\tcase *opBitShl:\n\t\treturn expr.compileShift(c, -1)\n\tcase *opBitShr:\n\t\treturn expr.compileShift(c, 1)\n\tdefault:\n\t\tpanic(\"unexpected arithmetic operator\")\n\t}\n}\n\nvar (\n\t_ opBitBinary = (*opBitAnd)(nil)\n\t_ opBitBinary = (*opBitOr)(nil)\n\t_ opBitBinary = (*opBitXor)(nil)\n\t_ opBitShift  = (*opBitShl)(nil)\n\t_ opBitShift  = (*opBitShr)(nil)\n)\n","sourceCodeStart":312,"sourceCodeEnd":341,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/evalengine/expr_bit.go#L312-L341","documentation":"This panic comes from the evalengine's bit-expression compiler (compileBinary) when it encounters an *opBit* AST node type it does not recognize. It marks an internal invariant violation: the parser produced a bit operator node that the compiler's exhaustive switch was never taught to handle. It is not triggered by user SQL directly, but by a mismatch between the sqlparser AST and the evalengine IR translation layer.","triggerScenarios":"Calling compiler.compile on an expression IR tree that contains an unregistered opBitBinary variant (i.e., a type implementing opBitBinary that is not *opBitAnd, *opBitOr, *opBitXor, *opBitShl, or *opBitShr). Practically this happens only when new bit operators are added to the IR without updating compileBinary's switch.","commonSituations":"Developers extending the evalengine with a new bit operator; running against a Vitess build where parser and evalengine were updated out of sync (mixed-version or patched build); fuzzing or constructing IR nodes programmatically in tests.","solutions":["Check the evalengine IR type that reached compileBinary and confirm which opBitBinary variant is unhandled","Add a case for the missing operator in compileBinary in go/vt/vtgate/evalengine/expr_bit.go, mapping it to the appropriate BitOp asm opcode","Regenerate/rebuild so parser-generated IR and the compiler switch are in sync","If seen on a released build without local changes, file a Vitess bug with the failing query"],"exampleFix":"// before\ncase *opBitShr:\n\treturn expr.compileShift(c, 1)\ndefault:\n\tpanic(\"unexpected arithmetic operator\")\n// after\ncase *opBitShr:\n\treturn expr.compileShift(c, 1)\ncase *opBitNewOp:\n\treturn expr.compileBinary(c, c.asm.BitOp_new_bb, c.asm.BitOp_new_uu)\ndefault:\n\tpanic(\"unexpected arithmetic operator\")","handlingStrategy":"validation","validationCode":"// Before compiling custom IR, ensure the bit op is a known variant\nfunc isKnownBitOp(op evalengine.IR) bool {\n\tswitch op.(type) {\n\tcase *evalengine.BitAnd, *evalengine.BitOr, *evalengine.BitXor, *evalengine.BitShl, *evalengine.BitShr:\n\t\treturn true\n\t}\n\treturn false\n}","typeGuard":"if bo, ok := expr.(*evalengine.BitBinaryOp); ok && isKnownBitOp(bo) { /* safe to compile */ }","tryCatchPattern":"func safeCompile(e evalengine.IR) (ct evalengine.ctype, err error) {\n\tdefer func() {\n\t\tif r := recover(); r != nil {\n\t\t\terr = fmt.Errorf(\"compile panic: %v\", r)\n\t\t}\n\t}()\n\treturn e.compile(compiler)\n}","preventionTips":["When adding opBitBinary variants, update compileBinary's switch in the same PR","Add exhaustive-switch linters (exhaustive) for IR compile switches","Add unit tests compiling every bit operator IR type","Keep sqlparser and evalengine built from the same commit"],"tags":["evalengine","panic","internal-invariant","bit-operations"],"backgroundTag":"unhandled-switch-case-panic","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}