vitessio/vitess · error
number too big to be stored in double: %q
Error message
number too big to be stored in double: %q
What it means
The parsed numeric literal is larger than what a float64 can represent (mayExceedFloat64 says the exponent/digit count overflows a double) and it also does not fit a MySQL integer, so the parser refuses to store it. This protects consumers from silently losing precision or overflowing.
Source
Thrown at go/mysql/json/parser.go:206
}
if s[0] == 'n' {
if len(s) < len("null") || s[:len("null")] != "null" {
return nil, s, fmt.Errorf("unexpected value found: %q", startEndString(s))
}
return ValueNull, s[len("null"):], nil
}
flen, exponent, ok := readFloat(s)
if !ok {
return nil, s[flen:], fmt.Errorf("invalid number in JSON string: %q", startEndString(s))
}
v := c.getValue()
v.t = TypeNumber
v.s = s[:flen]
v.n = numberTypeRaw
if mayExceedFloat64(v.s, exponent) && !mysqlNumberFits(v.s) {
return nil, s, fmt.Errorf("number too big to be stored in double: %q", startEndString(v.s))
}
return v, s[flen:], nil
}
// maxFloat64Digits is how far a decimal point can travel before a double runs
// out of room. The largest double is under 1.8e308, so a written exponent of
// 308 always leaves somewhere for the number to land and 309 need not.
const maxFloat64Digits = 308
// mayExceedFloat64 reports whether num is worth converting to find out whether a
// double can hold it. It errs towards yes: the job is to keep the conversion off
// the common path, not to answer the question.
//
// What can carry a number that far is the digits in front of its decimal point,
// moved by its exponent — it stays below 10^309 whenever those two together stay
// inside the places a double has, whatever it goes on to say after the point.
// Digits behind the point only ever move it the other way, and they are what buys
// the written exponent its extra room; nor can they overflow the significand onView on GitHub (pinned to 01a25a7d17)
Solutions
- Reduce the magnitude of the number in the JSON document
- Store the value as a string if extreme magnitude is intentional
- Clamp/round numbers at serialization time before embedding them in JSON
Example fix
// before
v, err := mysql.ParseJSON("1e400")
// after
v, err := mysql.ParseJSON("1e308") // or "\"1e400\"" as a string Defensive patterns
Strategy: validation
Validate before calling
func numberFitsDouble(s string) bool {
f, err := strconv.ParseFloat(s, 64)
return err == nil && !math.IsInf(f, 0)
} Try / catch
v, err := mysql.ParseJSON(input)
if err != nil {
if strings.Contains(err.Error(), "too big to be stored in double") {
// clamp the value or store as string instead
}
return err
} Prevention
- Clamp extreme numeric values at serialization time
- Store out-of-range magnitudes as strings if precision matters
- Sanitize computed values (e.g. from division or exp) for Infinity before embedding in JSON
When it happens
Trigger: Calling Parse on a JSON document containing a number whose magnitude exceeds ~1.8e308 or has more significant digits than a double can hold, e.g. `1e400`.
Common situations: Scientific datasets with extreme values; auto-generated data with sentinel values like 1e999; bad calculations upstream producing Infinity-like literals.
Related errors
- invalid number at position %d in JSON
- invalid number in JSON string: %q
- overflow
- Invalid JSON path expression.
- cannot parse int64 from %q: %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/5ac0a20a91e6c30c.
Report an issue: GitHub.