redis/go-redis · error
redis: FT.AGGREGATE COLLECT: empty field name in Fields
Error message
redis: FT.AGGREGATE COLLECT: empty field name in Fields
What it means
The COLLECT aggregation step's FIELDS list must contain non-empty field names. buildCollectArgs validates each entry, stripping a leading '@'; an entry that is empty or only '@' names no attribute, so argument building aborts with this error before the command is sent.
Source
Thrown at search_collect.go:94
return "@" + strings.TrimLeft(name, "@")
}
// buildCollectArgs renders a FTAggregateCollect into the reducer argument
// token list (everything after "REDUCE COLLECT <narg>", excluding AS <alias>).
// The serializer computes <narg> as len(args), which matches the COLLECT
// contract: narg counts every FIELDS/DISTINCT/SORTBY/LIMIT token.
func buildCollectArgs(o FTAggregateCollect) ([]interface{}, error) {
args := make([]interface{}, 0, 8)
// FIELDS (required): either * or a counted list of @-names.
switch {
case o.FieldsAll:
args = append(args, "FIELDS", "*")
case len(o.Fields) > 0:
args = append(args, "FIELDS", len(o.Fields))
for _, f := range o.Fields {
if strings.TrimLeft(f, "@") == "" {
return nil, fmt.Errorf("redis: FT.AGGREGATE COLLECT: empty field name in Fields")
}
args = append(args, ensureAtPrefix(f))
}
default:
return nil, fmt.Errorf("redis: FT.AGGREGATE COLLECT requires FieldsAll or a non-empty Fields list")
}
// DISTINCT (optional, forward-compatible).
if o.Distinct {
args = append(args, "DISTINCT")
}
// SORTBY (optional). sort_narg counts each field plus its optional
// direction token.
if len(o.SortBy) > 0 {
sortTokens := make([]interface{}, 0, len(o.SortBy)*2)
for _, s := range o.SortBy {
if strings.TrimLeft(s.FieldName, "@") == "" {View on GitHub (pinned to c5cad058c7)
Solutions
- Replace empty/'@'-only entries in Fields with actual field names (with or without the '@' prefix)
- Filter out empty strings before constructing the Collect reducer
- Validate the field list at config-load time
Example fix
// before
r := redis.NewCollectReducer(redis.CollectOptions{Fields: []string{"@", "@age"}})
// after
r := redis.NewCollectReducer(redis.CollectOptions{Fields: []string{"@name", "@age"}}) Defensive patterns
Strategy: validation
Validate before calling
for _, f := range fields {
if strings.TrimLeft(f, "@") == "" {
return fmt.Errorf("invalid COLLECT field: %q", f)
}
} Prevention
- Never pass user-supplied field names without trimming and emptiness checks
- Use FieldsAll instead of a placeholder Fields list when all fields are wanted
- Sanitize config-driven field lists at startup
When it happens
Trigger: NewCollectReducer with CollectOptions.Fields containing "" or "@"; buildCollectArgs hits strings.TrimLeft(f, "@") == "" and returns nil plus this error.
Common situations: Building COLLECT field lists programmatically from user input or config where a field was left blank; a stray '@' typo instead of a field name like '@name'.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- redis: FT.AGGREGATE COLLECT requires FieldsAll or a non-empt
- redis: FT.AGGREGATE COLLECT: empty field name in SortBy
- redis: FT.AGGREGATE COLLECT: ASC and DESC are mutually exclu
- FT.AGGREGATE: SortByMax must follow a SortBy step
- redis: COLLECT value has type %T, want array of entries
AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01).
Data as JSON: /api/errors/63cfb02eb21b44fe.
Report an issue: GitHub.