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 on

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Reduce the magnitude of the number in the JSON document
  2. Store the value as a string if extreme magnitude is intentional
  3. 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

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


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