vitessio/vitess · error
invalid number in JSON string: %q
Error message
invalid number in JSON string: %q
What it means
readFloat failed to recognize a valid floating-point number at the current position, so parseValue reports the fragment as an invalid number. MySQL JSON numbers must parse as a JSON number literal (digits, optional sign, fraction, exponent).
Source
Thrown at go/mysql/json/parser.go:198
}
return ValueTrue, s[len("true"):], nil
}
if s[0] == 'f' {
if len(s) < len("false") || s[:len("false")] != "false" {
return nil, s, fmt.Errorf("unexpected value found: %q", startEndString(s))
}
return ValueFalse, s[len("false"):], nil
}
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 aView on GitHub (pinned to 01a25a7d17)
Solutions
- Fix the malformed numeric literal in the input string
- Ensure numbers are serialized with a proper JSON encoder, not string formatting
- Check for truncation/corruption in the source of the JSON payload
Example fix
// before
v, err := mysql.ParseJSON("1.2.3")
// after
v, err := mysql.ParseJSON("1.23") Defensive patterns
Strategy: validation
Validate before calling
// ensure numbers are JSON-valid before embedding
func jsonNumber(n float64) string {
b, _ := json.Marshal(n)
return string(b)
} Try / catch
v, err := mysql.ParseJSON(input)
if err != nil {
if strings.Contains(err.Error(), "invalid number in JSON") {
// reject or re-serialize the document with a proper encoder
}
return err
} Prevention
- Serialize numbers via encoding/json or strconv.FormatFloat, never fmt.Sprintf with locale settings
- Reject documents that mix commas/periods in decimals at ingest
- Watch for truncation when reading payloads from the network or binlog
When it happens
Trigger: parseValue encountering input like `1.2.3`, `--5`, `1e`, or a number immediately followed by an invalid character such as `1a` when calling Parse.
Common situations: Corrupted numeric data in a binlog event or JSON column; code generating numbers with locale formatting (e.g. `1,5`); truncated payloads cut mid-number.
Related errors
- invalid number at position %d in JSON
- range %d should be >= %d
- unexpected character %q in JSON
- expected ',' or '}' in object, got %q
- reading JSON object key: %w
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/309ffc89f3406135.
Report an issue: GitHub.