{"record":{"id":"81bcd4a5aa6afcd6","repo":"redis/go-redis","slug":"redis-can-t-parse-int-reply-100q","errorCode":null,"errorMessage":"redis: can't parse int reply: %.100q","messagePattern":"redis: can't parse int reply: %\\.100q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/reader.go","lineNumber":516,"sourceCode":"\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\n\t\t}\n\t\treturn strconv.ParseUint(s, 10, 64)\n\tcase RespBigInt:\n\t\tb, err := r.readBigInt(line)","sourceCodeStart":498,"sourceCodeEnd":534,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/internal/proto/reader.go#L498-L534","documentation":"ReadInt expects the reply line to be one of the numeric-ish reply types: RESP3 integer, status string, or bulk string containing a decimal integer. If the first byte of the reply line is any other type marker (e.g. an array, map, float, nil, or error framing that isn't a RedisError), the parser cannot convert it and returns 'redis: can't parse int reply: <line prefix>'. This is a reply-type mismatch: the command sent does not match what the caller is trying to decode.","triggerScenarios":"Calling .Int()/.Int64() on a command whose reply isn't an integer — e.g. calling Int() on GET that returned a string 'abc', calling Int() on a command that returned an array/map/float/bool, or routing a command to the wrong endpoint so the reply type differs from expectation (via readReply, readXMessage, readStreamGroups, readXInfoStreamGroupPending, readXInfoStreamConsumers, readEngines). Also triggered when a status reply contains non-numeric text (e.g. 'OK' or 'PONG') and the code expects an int.","commonSituations":"Misusing a generic Do()/NewCommand result by calling .Int() without knowing the reply shape; a Lua script whose return type changed (e.g. returning a table instead of a number); server version differences where a command returns a float (Redis 6.2+ INCRBYFLOAT-like paths) but the code parses Int; proxy or cluster middleware that rewrites replies into different types.","solutions":["Log the command and its raw reply type first (cmd.String() / redis.NewStringResult) to see the actual shape, then pick the matching accessor: .Text() for strings, .Int() only for numeric replies.","Use cmd.Result() on the correct typed command (e.g. StringCmd for GET, SliceCmd for arrays) instead of forcing Int().","If a status string may be non-numeric ('OK', 'PONG'), handle it explicitly before calling Int().","Verify the server/proxy isn't rewriting reply types; compare reply shapes with redis-cli --resp (RESP3) directly against the same endpoint."],"exampleFix":"// before: assumes numeric reply\nn, err := client.Do(ctx, \"GET\", key).Int64()\n// after: handle string reply explicitly\nv, err := client.Do(ctx, \"GET\", key).Result()\nif err != nil { return err }\ns, ok := v.(string)\nif !ok { return fmt.Errorf(\"unexpected reply type %T\", v) }\nn, err := strconv.ParseInt(s, 10, 64)","handlingStrategy":"type-guard","validationCode":"// Before forcing an int conversion, inspect the raw reply type:\n// prefer the typed command classes (StringCmd, IntCmd, SliceCmd) over raw Do().\nfunc replyIsNumeric(v interface{}) bool {\n    switch v.(type) {\n    case int64, string:\n        return true\n    }\n    return false\n}","typeGuard":"func asInt64(v interface{}) (int64, bool) {\n    switch t := v.(type) {\n    case int64:\n        return t, true\n    case string:\n        n, err := strconv.ParseInt(t, 10, 64)\n        return n, err == nil\n    }\n    return 0, false\n}","tryCatchPattern":"n, err := client.Do(ctx, \"GET\", key).Int64()\nif err != nil {\n    if strings.HasPrefix(err.Error(), \"redis: can't parse int reply:\") {\n        return fmt.Errorf(\"reply shape mismatch for GET %s — check command/endpoint: %w\", key, err)\n    }\n    return err\n}","preventionTips":["Always use the typed command API (Get -> StringCmd, Incr -> IntCmd) instead of raw Do()+Int().","Match the accessor to the known reply type of the command; when unsure, log cmd.String() first.","Re-check reply shapes after server upgrades — some commands changed return types across Redis versions.","Validate Lua script return types in CI by calling them against a real Redis in tests."],"tags":["go","redis","type-mismatch","reply-parsing"],"backgroundTag":"reply-type-mismatch","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}