vitessio/vitess · warning

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

Error message

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

What it means

ParseInt64 parses the leading digits successfully but finds trailing characters that are neither digits nor space/tab (space/tab are consumed as trailing whitespace). It returns the parsed value together with this error identifying the unconsumed tail. This matches MySQL's lenient '123abc' -> 123 coercion semantics while still signalling the problem.

Source

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

		if d == math.MaxInt64+1 {
			v = math.MinInt64
		}
	}

	if i <= j {
		return v, fmt.Errorf("cannot parse int64 from %q", s)
	}

	for i < uint(len(s)) {
		if !isSpace(s[i]) {
			break
		}
		i++
	}

	if i < uint(len(s)) {
		// Unparsed tail left.
		return v, fmt.Errorf("unparsed tail left after parsing int64 from %q: %q", s, s[i:])
	}
	if d == math.MaxInt64+1 && minus {
		v = math.MinInt64
	}

	return v, nil
}

// ParseFloat64 parses floating-point number s.
//
// It is equivalent to strconv.ParseFloat(s, 64) in case it succeeds,
// but on error it will return the best effort value of what it has parsed so far.
func ParseFloat64(s string) (float64, error) {
	if len(s) == 0 {
		return 0.0, errors.New("cannot parse float64 from empty string")
	}
	i := uint(0)
	for i < uint(len(s)) {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Treat the error as invalid input and reject, unless MySQL-style truncation semantics are desired.
  2. Route strings containing '.' or 'e' to fastparse.ParseFloat64 instead.
  3. Trim/clean the input (strip units, split on delimiters) before integer parsing.

Example fix

// before
v, err := fastparse.ParseInt64(s, 10)
// after
v, err := fastparse.ParseInt64(s, 10)
if err != nil && strings.Contains(err.Error(), "unparsed tail") {
    return vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "trailing characters in integer literal %q", s)
}
Defensive patterns

Strategy: validation

Validate before calling

var intRe = regexp.MustCompile(`^-?[0-9]+$`)

func strictInt64(s string) (int64, error) {
    if !intRe.MatchString(strings.TrimSpace(s)) {
        return 0, vterrors.Errorf(vtrpcpb.Code_INVALID_ARGUMENT, "not a plain integer: %q", s)
    }
    return fastparse.ParseInt64(s, 10)
}

Try / catch

v, err := fastparse.ParseInt64(s, 10)
if err != nil {
    // parsed value v is prefix-only; do not use unless truncation is intended
    return 0, vterrors.Wrapf(err, vtrpcpb.Code_INVALID_ARGUMENT, "integer literal %q has trailing characters", s)
}

Prevention

When it happens

Trigger: ParseInt64("123abc", 10), ParseInt64("12.5", 10) (the '.' stops digit parsing), or "0x1F" parsed with base 10.

Common situations: String-to-int SQL coercions of mixed content, CSV fields with stray characters or units ("42ms"), decimal literals wrongly routed to integer parsing.

Related errors


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