redis/go-redis · error
redis: unexpected response %#v
Error message
redis: unexpected response %#v
What it means
In the same reply transformer as error 61, the RESP2 branch expects the reply to be a []interface{} of []interface{} pairs (array of [key, value] arrays). If an element is not a []interface{}, it cannot be turned into a map, so the parser returns `redis: unexpected response` with the whole reply printed via %#v.
Source
Thrown at command.go:6374
return err
}
resultMap := map[string]interface{}{}
switch midResponse := data.(type) {
case map[interface{}]interface{}: // resp3 will return map
for k, v := range midResponse {
stringKey, ok := k.(string)
if !ok {
return fmt.Errorf("redis: invalid map key %#v", k)
}
resultMap[stringKey] = v
}
case []interface{}: // resp2 will return array of arrays
n := len(midResponse)
for i := 0; i < n; i++ {
finalArr, ok := midResponse[i].([]interface{}) // final array that we need to transform to map
if !ok {
return fmt.Errorf("redis: unexpected response %#v", data)
}
m := len(finalArr)
if m%2 != 0 { // since this should be map, keys should be even number
return fmt.Errorf("redis: unexpected response %#v", data)
}
for j := 0; j < m; j += 2 {
stringKey, ok := finalArr[j].(string) // the first one
if !ok {
return fmt.Errorf("redis: invalid map key %#v", finalArr[i])
}
resultMap[stringKey] = finalArr[j+1] // second one is value
}
}
default:
return fmt.Errorf("redis: unexpected response %#v", data)
}
View on GitHub (pinned to c5cad058c7)
Solutions
- Read the %#v dump in the error — it shows the exact reply shape the server sent; compare with what your Redis version should return.
- Try `Protocol: 3` (RESP3) so the map-native branch of the transformer is used instead of the array-of-arrays path.
- Upgrade go-redis and/or the server so both agree on the reply format.
- If a proxy is in the path, inspect and fix its reply translation, or bypass it for this command.
Example fix
// before: RESP2 reply flattened by a proxy
cfg := &redis.Options{Addr: addr, Protocol: 2}
// after: use RESP3 so maps arrive as maps
cfg := &redis.Options{Addr: addr, Protocol: 3} Defensive patterns
Strategy: try-catch
Type guard
func isArrayOfPairArrays(v interface{}) bool {
arr, ok := v.([]interface{})
if !ok {
return false
}
for _, e := range arr {
if _, ok := e.([]interface{}); !ok {
return false
}
}
return true
} Try / catch
res, err := cmd.Result()
if err != nil {
if strings.Contains(err.Error(), "unexpected response") {
// log raw reply shape captured via ProcessHook, then fall back
log.Printf("unexpected reply shape: %v", err)
return nil, errReplyShape
}
return err
} Prevention
- Set `Protocol: 3` to use RESP3 maps and avoid the RESP2 array-of-arrays path.
- Test against the exact server/proxy stack used in production.
- Bypass reply-rewriting proxies for map-shaped commands.
- Upgrade go-redis when you upgrade the Redis server.
When it happens
Trigger: Calling a command routed through this map transformer under RESP2 when the server/proxy returns a flat array, a scalar, or nested structures instead of an array of 2-element arrays — typically with FUNCTION LIST-like replies from a non-Redis server or a version whose shape changed.
Common situations: Redis-compatible servers (Dragonfly, KeyDB) or proxies reshaping replies; server version newer than the client expects; RESP2 vs RESP3 mismatches (Protocol: 2 vs 3) selecting the other code path.
Related errors
- redis: got %d elements in latency get, expected at least 4
- redis: invalid map key %#v
- redis: function list unexpected key %s
- redis: function stats unexpected key %s
- redis: VectorScoreSliceCmd expects even number of elements,
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/bf4e6829d20ac533.
Report an issue: GitHub.