{"id":"cd847a43dce092b0","repo":"go-redis/redis","slug":"redis-got-d-elements-in-the-sorted-set-array-wa","errorCode":null,"errorMessage":"redis: got %d elements in the sorted set array, wanted a multiple of 2","messagePattern":"redis: got (.+?) elements in the sorted set array, wanted a multiple of 2","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command.go","lineNumber":4423,"sourceCode":"\t}\n\n\t// If the n is 0, can't continue reading.\n\tif n == 0 {\n\t\tcmd.val = make([]Z, 0)\n\t\treturn nil\n\t}\n\n\ttyp, err := rd.PeekReplyType()\n\tif err != nil {\n\t\treturn err\n\t}\n\tarray := typ == proto.RespArray\n\n\tif array {\n\t\tcmd.val = make([]Z, n)\n\t} else {\n\t\tif n%2 != 0 {\n\t\t\treturn fmt.Errorf(\"redis: got %d elements in the sorted set array, wanted a multiple of 2\", n)\n\t\t}\n\t\tcmd.val = make([]Z, n/2)\n\t}\n\n\tfor i := 0; i < len(cmd.val); i++ {\n\t\tif array {\n\t\t\tif err = rd.ReadFixedArrayLen(2); err != nil {\n\t\t\t\treturn err\n\t\t\t}\n\t\t}\n\n\t\tif cmd.val[i].Member, err = rd.ReadString(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif cmd.val[i].Score, err = rd.ReadFloat(); err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":4405,"sourceCodeEnd":4441,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/command.go#L4405-L4441","documentation":"Returned by ZSliceCmd.readReply (command.go:4423, used by ZRangeWithScores, ZPopMin/Max, ZInterWithScores, ZUnionWithScores, ZRangeByScoreWithScores, ZRandMemberWithScores, ZDiffWithScores). The reply is either a RESP3 array-of-pairs or a RESP2 flat [member,score,member,score,...] array; a flat RESP2 array with an odd element count cannot be split into member/score pairs and is reported rather than silently mis-parsing.","triggerScenarios":"Calling a *WithScores sorted-set command with the client on RESP2 and the server returning an odd-length array — typically a sign of corruption, a proxy rewriting the frame, or a Redis build with a non-standard reply shape.","commonSituations":"A RESP-mangling proxy (twemproxy and friends) between client and Redis; an experimental/patched Redis; rare memory/link corruption. Legitimate Redis builds always return even-length flat arrays for these commands.","solutions":["Switch the client to RESP3 (Options.Protocol = 3) so the reply arrives as a proper array-of-pairs.","Remove or bypass any proxy that may be rewriting RESP frames, and connect directly to Redis.","Capture a RESP trace (tcpdump/redis-cli) to confirm whether Redis or an intermediary is producing the odd length; file a bug against the offender."],"exampleFix":"// before\nopts := redis.Options{Addr: addr /* RESP2 */}\nrdb := redis.NewClient(&opts)\nmembers, err := rdb.ZRangeWithScores(ctx, \"s\", 0, -1).Result() // odd length → error\n\n// after\nopts := redis.Options{Addr: addr, Protocol: 3}\nrdb := redis.NewClient(&opts)\nmembers, err := rdb.ZRangeWithScores(ctx, \"s\", 0, -1).Result()","handlingStrategy":"try-catch","validationCode":"// Prefer RESP3 so sorted-set *WithScores commands arrive as array-of-pairs.\nopts := redis.Options{Addr: addr, Protocol: 3}","typeGuard":null,"tryCatchPattern":"members, err := rdb.ZRangeWithScores(ctx, \"s\", 0, -1).Result()\nif err != nil && strings.Contains(err.Error(), \"sorted set array, wanted a multiple of 2\") {\n    // odd-length RESP2 array — switch to RESP3 or bypass any proxy\n}","preventionTips":["Use RESP3 for *WithScores sorted-set commands.","Connect directly to Redis, bypassing RESP-mangling proxies.","Capture a RESP trace to identify the source of odd-length arrays."],"tags":["command","reply-parsing","sorted-set","resp3","protocol-mismatch"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}