{"id":"0a9f2eaad7f3432d","repo":"go-redis/redis","slug":"redis-got-d-elements-in-the-key-value-array-wan","errorCode":null,"errorMessage":"redis: got %d elements in the key-value array, wanted a multiple of 2","messagePattern":"redis: got (.+?) elements in the key-value array, wanted a multiple of 2","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"command.go","lineNumber":2256,"sourceCode":"\t}\n\n\t// If the n is 0, can't continue reading.\n\tif n == 0 {\n\t\tcmd.val = make([]KeyValue, 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([]KeyValue, n)\n\t} else {\n\t\tif n%2 != 0 {\n\t\t\treturn fmt.Errorf(\"redis: got %d elements in the key-value array, wanted a multiple of 2\", n)\n\t\t}\n\t\tcmd.val = make([]KeyValue, 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].Key, err = rd.ReadString(); err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\tif cmd.val[i].Value, err = rd.ReadString(); err != nil {\n\t\t\treturn err\n\t\t}","sourceCodeStart":2238,"sourceCodeEnd":2274,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/command.go#L2238-L2274","documentation":"Returned by KeyValueSliceCmd.readReply (command.go:2256, used by HRandFieldWithValues) when the reply is a flat RESP2 array whose element count is odd. KeyValueSliceCmd accepts either a RESP3 array-of-pairs or a RESP2 flat [k,v,k,v,...] array; a flat array with an odd length cannot be split into key/value pairs and is reported rather than silently mis-parsing.","triggerScenarios":"Calling HRandFieldWithValues with the client using RESP2 (Protocol <= 2) and the server returning a malformed/odd-length array; or a Redis version/build where HRANDFIELD WITHVALUES produced an unexpected shape.","commonSituations":"Running against an old or patched Redis build that returns odd counts; a man-in-the-middle or proxy corrupting the byte stream; a future Redis change to HRANDFIELD reply shape.","solutions":["Switch the client to RESP3 (Options.Protocol = 3) so the reply comes as a proper array-of-pairs.","Upgrade Redis to a version known to return the documented HRANDFIELD WITHVALUES shape.","If the error persists, capture a RESP trace (e.g. via redis-cli MONITOR or a tcpdump) and file a bug — odd counts indicate corruption or a server bug."],"exampleFix":"// before\nopts := redis.Options{Addr: addr /* RESP2 default */}\nrdb := redis.NewClient(&opts)\nres, err := rdb.HRandFieldWithValues(ctx, \"h\", 5).Result() // odd-length → error\n\n// after\nopts := redis.Options{Addr: addr, Protocol: 3}\nrdb := redis.NewClient(&opts)\nres, err := rdb.HRandFieldWithValues(ctx, \"h\", 5).Result()","handlingStrategy":"try-catch","validationCode":"// Prefer RESP3 so HRANDFIELD WITHVALUES arrives as array-of-pairs.\nopts := redis.Options{Addr: addr, Protocol: 3}","typeGuard":null,"tryCatchPattern":"res, err := rdb.HRandFieldWithValues(ctx, \"h\", 5).Result()\nif err != nil && strings.Contains(err.Error(), \"wanted a multiple of 2\") {\n    // odd-length RESP2 array — switch to RESP3 or capture a RESP trace\n}","preventionTips":["Prefer RESP3 for hash/sorted-set commands that return pairs.","Pin a known-good Redis version.","On odd-length errors, suspect a proxy or corruption and capture a RESP trace."],"tags":["command","reply-parsing","resp3","hash","protocol-mismatch"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}