{"record":{"id":"309ffc89f3406135","repo":"vitessio/vitess","slug":"invalid-number-in-json-string-q","errorCode":null,"errorMessage":"invalid number in JSON string: %q","messagePattern":"invalid number in JSON string: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/json/parser.go","lineNumber":198,"sourceCode":"\t\t}\n\t\treturn ValueTrue, s[len(\"true\"):], nil\n\t}\n\tif s[0] == 'f' {\n\t\tif len(s) < len(\"false\") || s[:len(\"false\")] != \"false\" {\n\t\t\treturn nil, s, fmt.Errorf(\"unexpected value found: %q\", startEndString(s))\n\t\t}\n\t\treturn ValueFalse, s[len(\"false\"):], nil\n\t}\n\tif s[0] == 'n' {\n\t\tif len(s) < len(\"null\") || s[:len(\"null\")] != \"null\" {\n\t\t\treturn nil, s, fmt.Errorf(\"unexpected value found: %q\", startEndString(s))\n\t\t}\n\t\treturn ValueNull, s[len(\"null\"):], nil\n\t}\n\n\tflen, exponent, ok := readFloat(s)\n\tif !ok {\n\t\treturn nil, s[flen:], fmt.Errorf(\"invalid number in JSON string: %q\", startEndString(s))\n\t}\n\n\tv := c.getValue()\n\tv.t = TypeNumber\n\tv.s = s[:flen]\n\tv.n = numberTypeRaw\n\tif mayExceedFloat64(v.s, exponent) && !mysqlNumberFits(v.s) {\n\t\treturn nil, s, fmt.Errorf(\"number too big to be stored in double: %q\", startEndString(v.s))\n\t}\n\treturn v, s[flen:], nil\n}\n\n// maxFloat64Digits is how far a decimal point can travel before a double runs\n// out of room. The largest double is under 1.8e308, so a written exponent of\n// 308 always leaves somewhere for the number to land and 309 need not.\nconst maxFloat64Digits = 308\n\n// mayExceedFloat64 reports whether num is worth converting to find out whether a","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/json/parser.go#L180-L216","documentation":"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).","triggerScenarios":"parseValue encountering input like `1.2.3`, `--5`, `1e`, or a number immediately followed by an invalid character such as `1a` when calling Parse.","commonSituations":"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.","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"],"exampleFix":"// before\nv, err := mysql.ParseJSON(\"1.2.3\")\n// after\nv, err := mysql.ParseJSON(\"1.23\")","handlingStrategy":"validation","validationCode":"// ensure numbers are JSON-valid before embedding\nfunc jsonNumber(n float64) string {\n\tb, _ := json.Marshal(n)\n\treturn string(b)\n}","typeGuard":null,"tryCatchPattern":"v, err := mysql.ParseJSON(input)\nif err != nil {\n\tif strings.Contains(err.Error(), \"invalid number in JSON\") {\n\t\t// reject or re-serialize the document with a proper encoder\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["json","parsing","numbers"],"backgroundTag":"invalid-json-syntax","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}