go-redis/redis · error

unexpected type %T, want map or key/value array

Error message

unexpected type %T, want map or key/value array

What it means

Returned by parseCollectEntry when an individual COLLECT entry is neither a map (RESP3 map[interface{}]interface{} or map[string]interface{}) nor a flat key/value array ([]interface{}). The '%T' shows the actual Go type, e.g. string or int64, that appeared where an entry map was expected.

Source

Thrown at search_collect.go:233

		}
		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

  1. Inspect the raw reply (cmd.RawVal()) to identify the scalar and where it came from.
  2. Confirm the alias is exclusively used by a COLLECT reducer and not shared with another reducer/field.
  3. Verify the negotiated protocol (RESP2 vs RESP3) matches the server's reply type.
  4. Check server/proxy version and logs for an upstream error that was serialized into the results array.
Defensive patterns

Strategy: type-guard

Type guard

func isCollectEntryShape(e interface{}) bool {
	switch e.(type) {
	case map[interface{}]interface{}, map[string]interface{}, []interface{}:
		return true
	}
	return false
}

Try / catch

col, err := row.Collect(alias)
if err != nil {
    raw, _ := cmd.RawResult()
    log.Printf("COLLECT entry malformed on %q; raw=%v err=%v", alias, raw, err)
    return nil, err
}

Prevention

When it happens

Trigger: AggregateRow.Collect over an array whose element is a scalar (string, number, bulk-string error) rather than a per-entry map/array. Triggered purely during response decoding.

Common situations: Server returned an error string inline in the results array instead of as a top-level error. Protocol mismatch (RESP3 expected, RESP2 returned, or vice versa) causing the decoder to see a bare scalar. A non-COLLECT reducer's output landing in the same alias. Proxy rewriting the reply.

Related errors


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