vitessio/vitess · error
can't convert %q to decimal: too short
Error message
can't convert %q to decimal: too short
What it means
NewFromMySQL rejects an empty decimal payload. After an optional leading sign is stripped, if no characters remain there is nothing to parse, so it returns this error quoting the original input. This guards against empty binary strings or a bare sign like "-".
Source
Thrown at go/mysql/decimal/scan.go:104
return int32(totalLen - 1), int32(totalLen - 1 - idx)
}
func NewFromMySQL(s []byte) (Decimal, error) {
original := s
var neg bool
if len(s) > 0 {
switch s[0] {
case '+':
s = s[1:]
case '-':
neg = true
s = s[1:]
}
}
if len(s) == 0 {
return Decimal{}, fmt.Errorf("can't convert %q to decimal: too short", original)
}
if len(s) <= 18 {
dec, err := parseDecimal64(s)
if err == nil {
if neg {
dec.value.Neg(dec.value)
}
return dec, nil
}
if err != errOverflow {
return Decimal{}, fmt.Errorf("can't convert %s to decimal: %v", original, err)
}
}
var fractional, integral []byte
if pIndex := bytes.IndexByte(s, '.'); pIndex >= 0 {
if bytes.IndexByte(s[pIndex+1:], '.') != -1 {View on GitHub (pinned to 01a25a7d17)
Solutions
- Check the caller and fix the source so it never produces an empty or sign-only decimal payload.
- Add a length check on the wire data before calling NewFromMySQL and handle empty values explicitly (e.g. treat as NULL or zero).
- If a zero value is acceptable for empty input, default to NewFromMySQL([]byte("0")) at the call site.
Example fix
// before
dec, err := NewFromMySQL(data)
// after
if len(bytes.Trim(data, "+-")) == 0 {
dec, err = NewFromMySQL([]byte("0"))
} else {
dec, err = NewFromMySQL(data)
} Defensive patterns
Strategy: validation
Validate before calling
if len(bytes.Trim(data, "+-")) == 0 {
return fmt.Errorf("refusing to parse empty decimal payload")
} Try / catch
dec, err := decimal.NewFromMySQL(data)
if err != nil {
if strings.Contains(err.Error(), "too short") {
dec, err = decimal.NewFromMySQL([]byte("0")) // or treat as NULL
}
} Prevention
- Check for empty or sign-only payloads at the deserialization boundary.
- Treat empty DECIMAL wire data as NULL or zero explicitly per your domain semantics.
- Fix senders that truncate values to zero-length.
- Cover the empty-input case in unit tests for your decimal handling code.
When it happens
Trigger: Calling NewFromMySQL with a zero-length byte slice, or a slice containing only a '-' or '+' sign (the sign is stripped, leaving len(s)==0).
Common situations: A column value truncated to empty by a misbehaving sender; hand-written serialization code writing a sign but no digits; fuzz tests or adversarial clients feeding empty DECIMAL payloads.
Related errors
- overflow
- unexpected character %q
- can't convert %s to decimal: %v
- can't convert %s to decimal: too many .s
- too many .s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/82c608c786639fab.
Report an issue: GitHub.