{"record":{"id":"79259aec0b0b37da","repo":"redis/go-redis","slug":"redis-got-d-elements-in-the-array-wanted-d","errorCode":null,"errorMessage":"redis: got %d elements in the array, wanted %d","messagePattern":"redis: got (.+?) elements in the array, wanted (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/proto/reader.go","lineNumber":716,"sourceCode":"\treturn s == \"OK\" || s == \"1\" || s == \"true\", nil\n}\n\nfunc (r *Reader) ReadSlice() ([]interface{}, error) {\n\tline, err := r.ReadLine()\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\treturn r.readSlice(line)\n}\n\n// ReadFixedArrayLen read fixed array length.\nfunc (r *Reader) ReadFixedArrayLen(fixedLen int) error {\n\tn, err := r.ReadArrayLen()\n\tif err != nil {\n\t\treturn err\n\t}\n\tif n != fixedLen {\n\t\treturn fmt.Errorf(\"redis: got %d elements in the array, wanted %d\", n, fixedLen)\n\t}\n\treturn nil\n}\n\n// ReadArrayLen Read and return the length of the array.\nfunc (r *Reader) ReadArrayLen() (int, error) {\n\tline, err := r.ReadLine()\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\tswitch line[0] {\n\tcase RespArray, RespSet, RespPush:\n\t\treturn replyLen(line)\n\tdefault:\n\t\treturn 0, fmt.Errorf(\"redis: can't parse array/set/push reply: %.100q\", line)\n\t}\n}\n","sourceCodeStart":698,"sourceCodeEnd":734,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/internal/proto/reader.go#L698-L734","documentation":"ReadFixedArrayLen asserts the reply array has an exact expected number of elements. The server returned an array with a different count, so the fixed-shape contract (e.g. a positional reply where element order matters) is broken. This guards against silently misinterpreting positionally-encoded data.","triggerScenarios":"Calling ReadFixedArrayLen(n) (via readReply for commands like GEOPOS-style or readPosition, readXInfoStreamGroupPending, readXInfoStreamConsumers) when the server returns an array of a different length — typically a different Redis version changed the reply, or an error/NIL reply changed shape.","commonSituations":"Redis server version differences (a command gained/lost reply fields); Redis Cluster/proxy rewriting replies; running a command against Redis Enterprise or modules with altered output.","solutions":["Pin the Redis server version the reply shape was written for, or add version handling around the command","Check server version with INFO and compare against the parser's expected fixed length","If the reply legitimately varies, switch to ReadArrayLen and validate count dynamically instead of a fixed length","Confirm no proxy/cluster middleware is dropping or duplicating reply elements"],"exampleFix":"// before: strict fixed length\nerr := reader.ReadFixedArrayLen(2)\n// after: tolerant parse\nn, err := reader.ReadArrayLen()\nif err != nil { return err }\nif n != 2 { return fmt.Errorf(\"unexpected position reply arity %d\", n) }","handlingStrategy":"validation","validationCode":"// check server version compatibility before fixed-arity commands\ninfo, _ := client.Info(ctx, \"server\").Result()\n// compare redisVersion against the version the reply shape was written for","typeGuard":null,"tryCatchPattern":"err := reader.ReadFixedArrayLen(2)\nif err != nil && strings.Contains(err.Error(), \"wanted\") {\n  return fmt.Errorf(\"reply shape changed, server version mismatch: %w\", err)\n}","preventionTips":["Pin Redis version per environment or gate parser on INFO server version","Prefer ReadArrayLen + dynamic validation for version-variable replies","Avoid mixed Redis versions behind one endpoint during upgrades","Snapshot replies with redis-cli --raw when bumping server versions"],"tags":["go-redis","resp-protocol","array","version-compat"],"backgroundTag":"unexpected-reply-shape","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}