vitessio/vitess · error

invalid decimal string: %q

Error message

invalid decimal string: %q

What it means

NewFromString parses human-readable decimal text and validates that the scanned characters form a complete, well-formed decimal. If no digits were seen (`!num`), the string ended before the scan consumed it (`i < maxLen`, e.g. trailing junk or a dangling exponent), or the exponent itself overflowed, it returns this error quoting the input.

Source

Thrown at go/mysql/decimal/scan.go:262

			expOverflow = true
		case e < -ExponentLimit:
			e = -ExponentLimit
			expOverflow = true
		}
		exp += e
	}

	d.exp = int32(exp)

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

	if !num || i < maxLen || expOverflow {
		err = fmt.Errorf("invalid decimal string: %q", s)
	}
	return d, err
}

func mulWW(x, y big.Word) (z1, z0 big.Word) {
	zz1, zz0 := bits.Mul(uint(x), uint(y))
	return big.Word(zz1), big.Word(zz0)
}

func mulAddWWW(x, y, c big.Word) (z1, z0 big.Word) {
	z1, zz0 := mulWW(x, y)
	if z0 = zz0 + c; z0 < zz0 {
		z1++
	}
	return z1, z0
}

func mulAddVWW(z, x []big.Word, y, r big.Word) (c big.Word) {

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Check the quoted input in the error and fix the value so it matches an optional sign, digits, optional single dot, optional exponent (e.g. -123.45e10).
  2. Pre-validate with a regexp such as ^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$ before calling NewFromString.
  3. Trim whitespace and strip currency/separator characters from user input first.
  4. Handle the error explicitly at the call site instead of ignoring it, and surface a user-friendly message.

Example fix

// before
d, err := decimal.NewFromString(input) // input = "12.3abc"

// after
if !decimalRe.MatchString(input) {
    return fmt.Errorf("not a decimal: %q", input)
}
d, err := decimal.NewFromString(input)
Defensive patterns

Strategy: validation

Validate before calling

var decimalRe = regexp.MustCompile(`^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$`)
if !decimalRe.MatchString(s) {
    return fmt.Errorf("not a valid decimal literal: %q", s)
}

Try / catch

d, err := decimal.NewFromString(s)
if err != nil {
    // error already quotes the input; wrap with caller context
    return vterrors.Wrapf(err, "parsing decimal from user input")
}

Prevention

When it happens

Trigger: Calling decimal.NewFromString with strings like "abc", "12.3.4", "1e" (dangling exponent), "1.5abc", "--2", "" (empty), or a number with an exponent too large for the internal representation.

Common situations: Parsing user or config input without prior validation; converting query results or query parameters that are not valid decimal literals; reading scientific-notation strings with unsupported exponent magnitude; application code assuming the value is always numeric.

Related errors


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