go-redis/redis · error
odd-length key/value array of length %d
Error message
odd-length key/value array of length %d
What it means
Returned by parseCollectEntry in the RESP2 branch when a flat key/value array has an odd number of elements. RESP2 represents each COLLECT entry as [field, value, field, value, ...], so an odd length means the frame is truncated or corrupt. The length is included to show how off it is.
Source
Thrown at search_collect.go:221
}
// parseCollectEntry decodes a single collected entry from either the RESP3
// map form or the RESP2 flat key/value array form into a CollectEntry. Keys
// are passed through as-is: the server already returns them without the "@"
// prefix.
func parseCollectEntry(e interface{}) (CollectEntry, error) {
switch m := e.(type) {
case map[interface{}]interface{}: // RESP3
out := make(CollectEntry, len(m))
for k, val := range m {
out[fmt.Sprint(k)] = val
}
return out, nil
case map[string]interface{}: // already string-keyed
return m, nil
case []interface{}: // RESP2 flat [field, value, field, value, ...]
if len(m)%2 != 0 {
return nil, fmt.Errorf("odd-length key/value array of length %d", len(m))
}
out := make(CollectEntry, len(m)/2)
for i := 0; i < len(m); i += 2 {
key, ok := m[i].(string)
if !ok {
key = fmt.Sprint(m[i])
}
out[key] = m[i+1]
}
return out, nil
default:
return nil, fmt.Errorf("unexpected type %T, want map or key/value array", e)
}
}
View on GitHub (pinned to 36d97525cd)
Solutions
- Check the server Redis version and patch level against the COLLECT feature requirements (8.8+).
- Capture the raw reply (cmd.RawResult()) and inspect the offending entry to confirm truncation.
- If a proxy is in front of Redis, bypass it to see if the corruption originates upstream.
- Report to the server/proxy maintainer with the raw frame; this shape should never be emitted by a conforming COLLECT implementation.
Defensive patterns
Strategy: try-catch
Type guard
func isEvenKVArray(e interface{}) bool {
arr, ok := e.([]interface{})
return ok && len(arr)%2 == 0
} Try / catch
col, err := row.Collect(alias)
if err != nil && strings.Contains(err.Error(), "odd-length key/value array") {
// server/proxy returned a truncated RESP2 entry; report raw frame
raw, _ := cmd.RawResult()
log.Printf("malformed COLLECT entry, raw=%v", raw)
}
return err Prevention
- Run COLLECT against a conforming Redis 8.8+ server; treat odd-length arrays as a server/proxy defect.
- Bypass any RESP-mangling proxy when diagnosing to localize the source.
- Log cmd.RawVal() alongside the decode error for forensic review.
When it happens
Trigger: AggregateRow.Collect decoding a RESP2 reply where one entry array has odd length (e.g. 3 or 5 elements). Surfaces during response decoding only; cannot be produced by local API misuse.
Common situations: A server/proxy bug truncating the entry array. RESP2/RESP3 confusion where a partial map leaks through as a half-array. Field count mismatch between what COLLECT projected and what the server emitted. Network-level frame corruption (rare).
Related errors
- redis: COLLECT value has type %T, want array of entries
- redis: COLLECT entry %d: %w
- unexpected type %T, want map or key/value array
- no data returned
- invalid total format
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/2238b893705e0bad.json.
Report an issue: GitHub.