vitessio/vitess · error
unexpected argument type
Error message
unexpected argument type
What it means
getMultiComparisonFunc picks the comparison strategy (numeric, temporal, text, etc.) for multi-argument comparisons like LEAST/GREATEST/INTERVAL based on the type signature of the arguments. The panic fires when the accumulated type counters don't match any known combination, meaning the typechecker allowed an argument-type mix this function never anticipated.
Source
Thrown at go/vt/vtgate/evalengine/fn_compare.go:256
if binary > 0 || text > 0 {
if text > 0 {
return compareAllText
}
if binary > 0 {
return compareAllBinary
}
} else {
if floats > 0 {
return compareAllFloat
}
if decimals > 0 {
return compareAllDecimal
}
if json > 0 {
return compareAllText
}
}
panic("unexpected argument type")
}
func compareAllTemporal(f func(env *ExpressionEnv, arg eval, prec int) *evalTemporal) multiComparisonFunc {
return func(env *ExpressionEnv, args []eval, cmp, prec int) (eval, error) {
var x *evalTemporal
for _, arg := range args {
conv := f(env, arg, prec)
if x == nil {
x = conv
continue
}
if (cmp < 0) == (conv.compare(x) < 0) {
x = conv
}
}
return x, nil
}
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Check the argument types passed to the function in the failing query and simplify/coerce them to a supported combination
- Update getMultiComparisonFunc to handle the missing type combination
- Strengthen the compile-time typecheck to reject unsupported mixes with a clear error instead of reaching the panic
- File a Vitess bug with the query and argument types if hit via normal SQL
Example fix
// before
if json > 0 {
return compareAllText
}
}
panic("unexpected argument type")
// after
if json > 0 {
return compareAllText
}
}
return compareAllText // documented fallback, or return an error instead of panicking Defensive patterns
Strategy: validation
Validate before calling
// Coerce LEAST/GREATEST arguments to a uniform type family before evaluating
func uniformArgTypes(args []sqltypes.Type) bool {
fam := typeFamily(args[0])
for _, a := range args[1:] {
if typeFamily(a) != fam {
return false
}
}
return true
} Type guard
func isSupportedArgMix(args []evalengine.eval) bool {
// supported: all numeric, all temporal, or string/json mixes handled by compareAllText
return uniformArgTypes(typesOf(args)) || countJSONOrString(args) == len(args)
} Try / catch
func safeMultiCompare(fn string, args []evalengine.eval) (v evalengine.eval, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("%s arg-type panic: %v", fn, r)
}
}()
return evalMultiCompare(fn, args)
} Prevention
- Pass homogeneous argument types to LEAST/GREATEST/INTERVAL (CAST as needed)
- Update getMultiComparisonFunc whenever adding new evalengine type kinds
- Reject unsupported type mixes at compile time with clear errors
- Add tests covering type-mix combinations for multi-arg functions
When it happens
Trigger: Evaluating LEAST/GREATEST/INTERVAL-style functions whose argument type combination (counts of numeric, temporal, json, text args) falls through all the if-branches of getMultiComparisonFunc — e.g., a mix of types the typechecker accepted but this dispatcher does not handle.
Common situations: Queries comparing exotic type mixes (e.g., temporal with JSON) through these functions; evalengine development where new type kinds were added without updating the dispatcher; tests building argument lists directly.
Related errors
- unreachable
- malformed hex literal from parser
- bad unsigned integer type
- bad type aggregation for signed/unsigned types
- unhandled case: evalIsTruthy
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/0bdfb197b2cf3c61.
Report an issue: GitHub.