redis/go-redis · error
odd-length key/value array of length %d
Error message
odd-length key/value array of length %d
What it means
Under RESP2 a COLLECT entry may arrive as a flat array [field, value, field, value, ...]. parseCollectEntry requires an even number of elements so each field pairs with a value; an odd-length array cannot be split into key/value pairs and fails with this error.
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 c5cad058c7)
Solutions
- Use RESP3 (Protocol: 3) so entries arrive as maps and this flat-array path is avoided
- Fix the proxy/truncation issue that dropped the trailing value
- Check the wrapped index from "redis: COLLECT entry %d" to locate the malformed row
Example fix
// before
[]interface{}{"field1", "v1", "field2"} // odd length
// after
[]interface{}{"field1", "v1", "field2", "v2"} // or switch to RESP3 maps Defensive patterns
Strategy: type-guard
Type guard
func isEvenKVArray(v interface{}) bool {
arr, ok := v.([]interface{})
return ok && len(arr)%2 == 0
} Prevention
- Prefer RESP3 so entries decode as maps, skipping the flat-array path
- Fix proxies/truncation that drop trailing values
- Validate hand-built test replies are even-length
When it happens
Trigger: parseCollectEntry receiving a []interface{} of odd length (e.g. a truncated or nil-valued final field) from a COLLECT reply; len(m)%2 != 0.
Common situations: RESP2 replies where a trailing value was dropped or a proxy mangled the entry; manually constructed test replies with a missing value.
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
- redis: VectorScoreSliceCmd expects even number of elements,
- redis: FT.AGGREGATE COLLECT: empty field name in Fields
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/00f9f0c8e1d29512.
Report an issue: GitHub.