redis/go-redis · error

bigInt(%s) value out of range

Error message

bigInt(%s) value out of range

What it means

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.

Source

Thrown at internal/proto/reader.go:512

	if err != nil {
		return 0, err
	}
	switch line[0] {
	case RespInt, RespStatus:
		return util.ParseInt(line[1:], 10, 64)
	case RespString:
		s, err := r.readStringReply(line)
		if err != nil {
			return 0, err
		}
		return strconv.ParseInt(s, 10, 64)
	case RespBigInt:
		b, err := r.readBigInt(line)
		if err != nil {
			return 0, err
		}
		if !b.IsInt64() {
			return 0, fmt.Errorf("bigInt(%s) value out of range", b.String())
		}
		return b.Int64(), nil
	}
	return 0, fmt.Errorf("redis: can't parse int reply: %.100q", line)
}

func (r *Reader) ReadUint() (uint64, error) {
	line, err := r.ReadLine()
	if err != nil {
		return 0, err
	}
	switch line[0] {
	case RespInt, RespStatus:
		return util.ParseUint(line[1:], 10, 64)
	case RespString:
		s, err := r.readStringReply(line)
		if err != nil {
			return 0, err

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Read the value as a string or big.Int instead: use cmd.Result() on a StringCmd / redis.NewStringResult and parse with strconv/big yourself.
  2. 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).
  3. 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.
  4. Under RESP2 big numbers are typically delivered as strings; if you don't need big-number semantics, run Protocol: 2 and parse manually.

Example fix

// before: panics into range error for huge values
n, err := client.Do(ctx, "MYCMD", key).Int64()
// after: read as string and parse as big.Int
s, err := client.Do(ctx, "MYCMD", key).Text()
if err != nil { return err }
b, ok := new(big.Int).SetString(s, 10)
if !ok { return fmt.Errorf("not a number: %s", s) }
Defensive patterns

Strategy: validation

Validate before calling

// Before calling Int(), check whether the command can plausibly exceed int64;
// for known-huge counters, use a string read path instead.
func useBigIntPath(cmd string) bool {
    return cmd == "BIGCOUNTER" || strings.HasPrefix(cmd, "TS.")
}

Type guard

func fitsInt64(s string) bool {
    b, ok := new(big.Int).SetString(s, 10)
    return ok && b.IsInt64()
}

Try / catch

n, err := cmd.Int64()
if err != nil {
    var overflow bool
    if strings.HasPrefix(err.Error(), "bigInt(") && strings.HasSuffix(err.Error(), "value out of range") {
        overflow = true
    }
    if overflow {
        return parseAsBigIntFromString(ctx, client, key) // fallback path
    }
    return err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/7f60fca8d7726f16. Report an issue: GitHub.