vitessio/vitess · warning

unparsed tail left after parsing float64 from %q: %q

Error message

unparsed tail left after parsing float64 from %q: %q

What it means

ParseFloat64 parses as many leading float characters as possible from the input; if after skipping trailing spaces/tabs there are still unconsumed characters, it returns the parsed value plus this error naming the leftover tail. Like ParseInt64, it implements MySQL's lenient prefix-parsing behavior while flagging the leftover content.

Source

Thrown at go/mysql/fastparse/fastparse.go:270

		if !isSpace(s[i]) {
			break
		}
		i++
	}
	ws := i

	// We only care to parse as many of the initial float characters of the
	// string as possible.
	val, l, err := Atof64(s[ws:])
	for l < len(s[ws:]) {
		if !isSpace(s[ws+uint(l)]) {
			break
		}
		l++
	}

	if l < len(s[ws:]) {
		return val, fmt.Errorf("unparsed tail left after parsing float64 from %q: %q", s, s[ws+uint(l):])
	}
	if errors.Is(err, strconv.ErrRange) {
		if val < 0 {
			val = -math.MaxFloat64
		} else {
			val = math.MaxFloat64
		}
	}

	return val, err
}

func isSpace(c byte) bool {
	switch c {
	case ' ', '\t':
		return true
	default:
		return false

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Reject the value when this error occurs unless truncation semantics are explicitly wanted.
  2. Normalize the input first: strip units, replace comma separators, trim whitespace.
  3. Use strconv.ParseFloat directly if strict full-string parsing is required.

Example fix

// before
val, err := fastparse.ParseFloat64(s)
// after
val, err := fastparse.ParseFloat64(s)
if err != nil && strings.Contains(err.Error(), "unparsed tail") {
    return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "invalid float literal %q", s)
}
Defensive patterns

Strategy: validation

Validate before calling

func strictFloat64(s string) (float64, error) {
    s = strings.TrimSpace(s)
    if _, err := strconv.ParseFloat(s, 64); err != nil {
        return 0, vterrors.Wrapf(err, vtrpcpb.Code_INVALID_ARGUMENT, "not a plain float: %q", s)
    }
    return fastparse.ParseFloat64(s)
}

Try / catch

val, err := fastparse.ParseFloat64(s)
if err != nil {
    return 0, vterrors.Wrapf(err, vtrpcpb.Code_INVALID_ARGUMENT, "invalid float literal %q", s)
}

Prevention

When it happens

Trigger: ParseFloat64("1.5abc"), ParseFloat64("1,234.5"), ParseFloat64("12e") or any string where Atof64 stops before the end and the remainder is not whitespace.

Common situations: Floating-point SQL literals with units or separators ("3.14rad"), locale-formatted numbers with comma thousands separators, or double-parsed values where a numeric string was embedded in longer text.

Related errors


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