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 a

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Fix the malformed numeric literal in the input string
  2. Ensure numbers are serialized with a proper JSON encoder, not string formatting
  3. 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

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


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