{"record":{"id":"5ac0a20a91e6c30c","repo":"vitessio/vitess","slug":"number-too-big-to-be-stored-in-double-q","errorCode":null,"errorMessage":"number too big to be stored in double: %q","messagePattern":"number too big to be stored in double: %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/mysql/json/parser.go","lineNumber":206,"sourceCode":"\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\n// double can hold it. It errs towards yes: the job is to keep the conversion off\n// the common path, not to answer the question.\n//\n// What can carry a number that far is the digits in front of its decimal point,\n// moved by its exponent — it stays below 10^309 whenever those two together stay\n// inside the places a double has, whatever it goes on to say after the point.\n// Digits behind the point only ever move it the other way, and they are what buys\n// the written exponent its extra room; nor can they overflow the significand on","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/mysql/json/parser.go#L188-L224","documentation":"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.","triggerScenarios":"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`.","commonSituations":"Scientific datasets with extreme values; auto-generated data with sentinel values like 1e999; bad calculations upstream producing Infinity-like literals.","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"],"exampleFix":"// before\nv, err := mysql.ParseJSON(\"1e400\")\n// after\nv, err := mysql.ParseJSON(\"1e308\") // or \"\\\"1e400\\\"\" as a string","handlingStrategy":"validation","validationCode":"func numberFitsDouble(s string) bool {\n\tf, err := strconv.ParseFloat(s, 64)\n\treturn err == nil && !math.IsInf(f, 0)\n}","typeGuard":null,"tryCatchPattern":"v, err := mysql.ParseJSON(input)\nif err != nil {\n\tif strings.Contains(err.Error(), \"too big to be stored in double\") {\n\t\t// clamp the value or store as string instead\n\t}\n\treturn err\n}","preventionTips":["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"],"tags":["json","numbers","overflow"],"backgroundTag":"number-out-of-range","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}