go-redis/redis · error

redis: got %d elements in the XMessage array, expected 2 or

Error message

redis: got %d elements in the XMessage array, expected 2 or 4

What it means

Returned by readXMessage (command.go:2822), used by every stream-read path (XREAD/XREADGROUP/XCLAIM/XAUTOCLAIM). Each XMessage is encoded as an array whose length is either 2 (id + field-values) or 4 (id + field-values + claim metadata: millis-since-delivery + delivered-count, from XAUTOCLAIM/XCLAIM). Any other length yields this error rather than reading garbage fields.

Source

Thrown at command.go:2822

	msgs := make([]XMessage, n)
	for i := 0; i < len(msgs); i++ {
		if msgs[i], err = readXMessage(rd); err != nil {
			return nil, err
		}
	}
	return msgs, nil
}

func readXMessage(rd *proto.Reader) (XMessage, error) {
	// Read array length can be 2 or 4 (with CLAIM metadata)
	n, err := rd.ReadArrayLen()
	if err != nil {
		return XMessage{}, err
	}

	if n != 2 && n != 4 {
		return XMessage{}, fmt.Errorf("redis: got %d elements in the XMessage array, expected 2 or 4", n)
	}

	id, err := rd.ReadString()
	if err != nil {
		return XMessage{}, err
	}

	v, err := stringInterfaceMapParser(rd)
	if err != nil {
		if err != proto.Nil {
			return XMessage{}, err
		}
	}

	msg := XMessage{
		ID:     id,
		Values: v,
	}

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Pin client and server to compatible Redis versions (XCLAIM metadata shape is version-dependent).
  2. If on a fork/patched Redis, switch to upstream or implement a custom parser via Do().
  3. Capture a RESP trace to confirm whether the server or a proxy is producing the unexpected length, then file a bug against the offender.

Example fix

// before
msgs, err := rdb.XRead(ctx, &redis.XReadArgs{Streams: []string{"s", "0"}}).Result()
// err: got N elements in the XMessage array, expected 2 or 4

// after — pin a compatible server, or fall back to raw parsing
raw, err := rdb.Do(ctx, "XREAD", "STREAMS", "s", "0").Result()
// type-switch on raw and decode manually
Defensive patterns

Strategy: try-catch

Try / catch

msgs, err := rdb.XRead(ctx, args).Result()
if err != nil && strings.Contains(err.Error(), "XMessage array, expected 2 or 4") {
    // unexpected stream reply shape — pin client/server versions or decode raw
}

Prevention

When it happens

Trigger: Reading from a stream where the server returns an XMessage array with a length other than 2 or 4 — e.g. a future Redis adding more claim fields, a proxy rewriting the frame, or stream-data corruption.

Common situations: Upgrading the client but not the server (or vice-versa) across a version that changed XCLAIM/XAUTOCLAIM reply shape; a RESP proxy corrupting array framing; a Redis fork/fork-patched build with different stream reply semantics.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/1a3deac99ee33d8d.json. Report an issue: GitHub.