redis/go-redis · error

redis: the length of the array must be a multiple of 2, got:

Error message

redis: the length of the array must be a multiple of 2, got: %d

What it means

When reading a map reply, the parser sometimes receives an RESP2 array (some commands and RESP2 encode maps as flat arrays). It then requires the array length to be even — each key needs a value. An odd length means the flat key/value stream is malformed, so decoding would misalign.

Source

Thrown at internal/proto/reader.go:766

// If responding to the array type (RespArray/RespSet/RespPush),
// it must be a multiple of 2 and return n/2.
// Other types will return an error.
func (r *Reader) ReadMapLen() (int, error) {
	line, err := r.ReadLine()
	if err != nil {
		return 0, err
	}
	switch line[0] {
	case RespMap:
		return replyLen(line)
	case RespArray, RespSet, RespPush:
		// Some commands and RESP2 protocol may respond to array types.
		n, err := replyLen(line)
		if err != nil {
			return 0, err
		}
		if n%2 != 0 {
			return 0, fmt.Errorf("redis: the length of the array must be a multiple of 2, got: %d", n)
		}
		return n / 2, nil
	default:
		return 0, fmt.Errorf("redis: can't parse map reply: %.100q", line)
	}
}

// DiscardNext read and discard the data represented by the next line.
func (r *Reader) DiscardNext() error {
	line, err := r.readLine()
	if err != nil {
		return err
	}
	return r.Discard(line)
}

// Discard the data represented by line.
func (r *Reader) Discard(line []byte) (err error) {

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Reset the connection after any read timeout/partial read instead of reusing it — desync is the usual cause
  2. Verify no proxy/load balancer truncates or rewrites multi-element replies
  3. Check the command's reply shape against the server version (some commands changed arity between versions)
  4. Re-run the failing command with redis-cli --raw and count the flat elements
Defensive patterns

Strategy: validation

Validate before calling

// odd flat-array length indicates desync — validate alignment upstream
// ensure prior replies consumed: err := cmd.Err(); consume full pipeline

Try / catch

n, err := reader.ReadMapLen()
if err != nil && strings.Contains(err.Error(), "multiple of 2") {
  logger.Error("map stream misaligned; dropping connection", "err", err)
  _ = conn.Close()
  return err
}

Prevention

When it happens

Trigger: ReadMapLen called (by readReply, stringInterfaceMapParser, readStreamGroups, readXInfoStreamConsumers, readFunctions, readEngines) when the reply arrives as an RESP2 array with an odd element count — a malformed or desynchronized stream, or a server/proxy producing a broken flat map encoding.

Common situations: Protocol desync after an earlier reply was partially read; buggy middleware rewriting HGETALL/XINFO-style replies; truncated reply from an aborted connection being reused.

Related errors


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