go-redis/redis · error
redis: COLLECT value has type %T, want array of entries
Error message
redis: COLLECT value has type %T, want array of entries
What it means
Returned by AggregateRow.Collect (via parseCollectValue) when the value stored under the requested alias is present but is not a []interface{}. The COLLECT reducer column is expected to be an array of per-entry maps/arrays, so any other concrete Go type (string, int64, map, nil-nonzero) is treated as a malformed/foreign value. The '%T' slot is filled with the actual Go type to aid diagnosis.
Source
Thrown at search_collect.go:192
// preserved as returned by the server; it is meaningful only when the COLLECT
// reducer was given a SORTBY.
func (r AggregateRow) Collect(alias string) (CollectColumn, error) {
v, ok := r.Fields[alias]
if !ok {
return nil, nil
}
return parseCollectValue(v)
}
// parseCollectValue decodes a raw COLLECT alias value (an array of entries)
// into a CollectColumn.
func parseCollectValue(v interface{}) (CollectColumn, error) {
if v == nil {
return nil, nil
}
arr, ok := v.([]interface{})
if !ok {
return nil, fmt.Errorf("redis: COLLECT value has type %T, want array of entries", v)
}
out := make(CollectColumn, 0, len(arr))
for i, e := range arr {
entry, err := parseCollectEntry(e)
if err != nil {
return nil, fmt.Errorf("redis: COLLECT entry %d: %w", i, err)
}
out = append(out, entry)
}
return out, nil
}
// 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) {View on GitHub (pinned to 36d97525cd)
Solutions
- Verify the alias passed to row.Collect matches the AS alias of a COLLECT reducer you actually added (and does not collide with other reducers/fields).
- Check REDIS_VERSION / search-enable-unstable-features is enabled on the server; COLLECT needs Redis 8.8+.
- Inspect row.Fields[alias] (or cmd.RawVal()) to see the actual type and shape returned by the server, then correct the alias or the reducer setup.
- If the alias legitimately holds a non-array under some rows, branch on type before calling Collect instead of assuming the shape.
Example fix
// before
col, err := row.Collect("price") // "price" is a plain LOAD field, not COLLECT
// after
col, err := row.Collect("collected_items") // matches NewCollectReducer(... As: "collected_items") Defensive patterns
Strategy: type-guard
Type guard
func isCollectColumn(v interface{}) bool {
if v == nil { return true }
_, ok := v.([]interface{})
return ok
}
// guard before calling Collect:
if v, ok := row.Fields[alias]; ok && !isCollectColumn(v) {
return fmt.Errorf("alias %q is not a COLLECT column: %T", alias, v)
} Try / catch
col, err := row.Collect(alias)
if err != nil {
// alias is not a COLLECT column or server reply is malformed;
// fall back to reading the raw value or skip the row
log.Printf("collect decode failed for %q: %v", alias, err)
return nil, err
} Prevention
- Use a unique AS alias for each COLLECT reducer that does not collide with LOAD/APPLY/other reducers.
- Confirm the server supports COLLECT (Redis 8.8+ with search-enable-unstable-features) before relying on it.
- Inspect cmd.RawVal() when this fires to confirm the actual server-side shape.
When it happens
Trigger: Calling row.Collect("myAlias") when "myAlias" is not actually a COLLECT output column (e.g. it collides with a regular GROUPBY reducer alias, a LOAD field, or an APPLY expression). Also possible after a server/protocol mismatch where the alias resolves to a scalar or a raw map instead of an array.
Common situations: Alias name collision: the COLLECT AS alias matches another reducer's alias or a projected field name. Reading a RESP3 vs RESP2 reply through an unexpected protocol setting. Server version that does not support COLLECT (requires Redis 8.8+ with search-enable-unstable-features) returning an error-shaped scalar under the same key. Calling Collect on an alias that was never declared as a COLLECT reducer.
Related errors
- unexpected type %T, want map or key/value array
- redis: COLLECT entry %d: %w
- odd-length key/value array of length %d
- invalid total format
- invalid row format
AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06).
Data as JSON: /data/errors/5fb8268cd988676b.json.
Report an issue: GitHub.