{"record":{"id":"7f60fca8d7726f16","repo":"redis/go-redis","slug":"bigint-s-value-out-of-range","errorCode":null,"errorMessage":"bigInt(%s) value out of range","messagePattern":"bigInt\\((.+?)\\) value out of range","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/reader.go","lineNumber":512,"sourceCode":"\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch line[0] {\n\tcase RespInt, RespStatus:\n\t\treturn util.ParseInt(line[1:], 10, 64)\n\tcase RespString:\n\t\ts, err := r.readStringReply(line)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\treturn strconv.ParseInt(s, 10, 64)\n\tcase RespBigInt:\n\t\tb, err := r.readBigInt(line)\n\t\tif err != nil {\n\t\t\treturn 0, err\n\t\t}\n\t\tif !b.IsInt64() {\n\t\t\treturn 0, fmt.Errorf(\"bigInt(%s) value out of range\", b.String())\n\t\t}\n\t\treturn b.Int64(), nil\n\t}\n\treturn 0, fmt.Errorf(\"redis: can't parse int reply: %.100q\", line)\n}\n\nfunc (r *Reader) ReadUint() (uint64, error) {\n\tline, err := r.ReadLine()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch line[0] {\n\tcase RespInt, RespStatus:\n\t\treturn util.ParseUint(line[1:], 10, 64)\n\tcase RespString:\n\t\ts, err := r.readStringReply(line)\n\t\tif err != nil {\n\t\t\treturn 0, err","sourceCodeStart":494,"sourceCodeEnd":530,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/internal/proto/reader.go#L494-L530","documentation":"ReadInt parses a reply into an int64. When the reply is a RESP3 big number (the '(' reply type), the value is parsed into a math/big.Int; if that number does not fit in an int64 (beyond ±9.2e18), the conversion is rejected with 'bigInt(%s) value out of range'. The library cannot silently truncate, so the caller must handle the oversized number explicitly.","triggerScenarios":"Any command parsed via ReadInt whose server reply is a RESP3 big number that exceeds int64 range — e.g. calling commands like GETRANGE-free INCRBY with a huge stored value, module commands (RedisTimeSeries, RedisBloom) returning big numbers, or XINFO/XREAD paths (readXMessage, readStreamGroups, readXInfoStreamGroupPending, readXInfoStreamConsumers, readEngines) when a field carries a huge numeric value with Protocol: 3.","commonSituations":"Using RESP3 (Protocol: 3) where the same query under RESP2 returned a string that you parsed manually; counters incremented beyond int64 (rare but possible via INCRBY with huge amounts or via modules); a module returning 128-bit integers as RESP3 big numbers while the caller expects int64.","solutions":["Read the value as a string or big.Int instead: use cmd.Result() on a StringCmd / redis.NewStringResult and parse with strconv/big yourself.","If the value legitimately exceeds int64, restructure the query (e.g. use a module command that returns a string, or clamp/scale the server-side value).","Check the concrete value printed in the error; if it's unexpected, inspect the data — an int64 overflow usually indicates corrupted or foreign data in the key.","Under RESP2 big numbers are typically delivered as strings; if you don't need big-number semantics, run Protocol: 2 and parse manually."],"exampleFix":"// before: panics into range error for huge values\nn, err := client.Do(ctx, \"MYCMD\", key).Int64()\n// after: read as string and parse as big.Int\ns, err := client.Do(ctx, \"MYCMD\", key).Text()\nif err != nil { return err }\nb, ok := new(big.Int).SetString(s, 10)\nif !ok { return fmt.Errorf(\"not a number: %s\", s) }","handlingStrategy":"validation","validationCode":"// Before calling Int(), check whether the command can plausibly exceed int64;\n// for known-huge counters, use a string read path instead.\nfunc useBigIntPath(cmd string) bool {\n    return cmd == \"BIGCOUNTER\" || strings.HasPrefix(cmd, \"TS.\")\n}","typeGuard":"func fitsInt64(s string) bool {\n    b, ok := new(big.Int).SetString(s, 10)\n    return ok && b.IsInt64()\n}","tryCatchPattern":"n, err := cmd.Int64()\nif err != nil {\n    var overflow bool\n    if strings.HasPrefix(err.Error(), \"bigInt(\") && strings.HasSuffix(err.Error(), \"value out of range\") {\n        overflow = true\n    }\n    if overflow {\n        return parseAsBigIntFromString(ctx, client, key) // fallback path\n    }\n    return err\n}","preventionTips":["Use Int64()/Int() only for commands whose range is bounded (counts, small counters).","For counters that can exceed int64, always read as string and parse with math/big.","Document expected reply ranges for every module command you call.","Add range assertions in tests using realistic max data to catch overflow early."],"tags":["go","redis","resp3","bigint","overflow"],"backgroundTag":"int64-overflow","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}