vitessio/vitess · error
unexpected Numeric type
Error message
unexpected Numeric type
What it means
Panic in the unary-minus compiler path of `compile`. The switch converts the argument's compile-time type into the negation result type: Int->Int/Uint->Float64/Decimal->Decimal, each emitting a matching ASM op. A numeric type outside that set (or an unset type) reaches `panic("unexpected Numeric type")`, meaning the type-coercion stage upstream let a non-negatable type through.
Source
Thrown at go/vt/vtgate/evalengine/expr_arithmetic.go:538
neg = sqltypes.Int64
c.asm.Neg_i()
}
case sqltypes.Uint64:
if arg.Flag&flagHex != 0 {
neg = sqltypes.Float64
c.asm.Neg_hex()
} else {
neg = sqltypes.Int64
c.asm.Neg_u()
}
case sqltypes.Float64:
neg = sqltypes.Float64
c.asm.Neg_f()
case sqltypes.Decimal:
neg = sqltypes.Decimal
c.asm.Neg_d()
default:
panic("unexpected Numeric type")
}
c.asm.jumpDestination(skip)
return ctype{
Type: neg,
Flag: nullableFlags(arg.Flag),
Size: arg.Size,
Scale: arg.Scale,
Col: collationNumeric,
}, nil
}
func nullableFlags(flag typeFlag) typeFlag {
return flag & (flagNull | flagNullable)
}
View on GitHub (pinned to 01a25a7d17)
Solutions
- Determine the argument type from the failing query and add the corresponding case (and ASM op) to the switch
- Tighten upstream coercion so only Int/Uint/Float64/Decimal reach this path
- Replace the panic with a wrapped internal error for graceful query failure
- Upgrade to a release that handles the type
Example fix
// before
default:
panic("unexpected Numeric type")
// after
default:
return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "cannot negate type %v", arg.Type) Defensive patterns
Strategy: type-guard
Validate before calling
switch arg.Type {
case sqltypes.Int64, sqltypes.Uint64, sqltypes.Float64, sqltypes.Decimal:
// ok
default:
return ctype{}, vterrors.Errorf(vtrpcpb.Code_INTERNAL, "unary minus on unsupported type %v", arg.Type)
} Type guard
func isNegatableNumeric(t sqltypes.Type) bool {
switch t {
case sqltypes.Int8, sqltypes.Int16, sqltypes.Int24, sqltypes.Int32, sqltypes.Int64,
sqltypes.Uint8, sqltypes.Uint16, sqltypes.Uint24, sqltypes.Uint32, sqltypes.Uint64,
sqltypes.Float32, sqltypes.Float64, sqltypes.Decimal:
return true
}
return false
} Try / catch
defer func() {
if r := recover(); r != nil {
err = vterrors.Errorf(vtrpcpb.Code_INTERNAL, "negation compile panic: %v", r)
}
}() Prevention
- Ensure upstream coercion normalizes all numeric types to the four switch cases
- Add compile tests for unary minus on every numeric type
- Fail with vterrors instead of panicking on unsupported types
When it happens
Trigger: Compiling `-expr` where the argument's resolved type is not one of the numeric types the switch expects (e.g. a newly added numeric type, or a type left at 0).
Common situations: Development-time issue after introducing new numeric sqltypes or changing coercion rules; on a released binary it would manifest as a vtgate panic for a specific unary-minus query.
Related errors
- did not compile?
- bad unsigned integer type
- negative stack position
- unhandled case: evalIsTruthy
- unsupported
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/5d4e124a766a0d73.
Report an issue: GitHub.