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

  1. Check the argument types passed to the function in the failing query and simplify/coerce them to a supported combination
  2. Update getMultiComparisonFunc to handle the missing type combination
  3. Strengthen the compile-time typecheck to reject unsupported mixes with a clear error instead of reaching the panic
  4. 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

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


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