redis/go-redis · error

redis: FT.AGGREGATE COLLECT requires FieldsAll or a non-empt

Error message

redis: FT.AGGREGATE COLLECT requires FieldsAll or a non-empty Fields list

What it means

buildCollectArgs requires exactly one of two field-selection modes for the COLLECT step: either FieldsAll (emitting FIELDS *) or a non-empty Fields list. If neither is set there is nothing to collect, so argument construction fails with this error.

Source

Thrown at search_collect.go:99

// 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, "@") == "" {
				return nil, fmt.Errorf("redis: FT.AGGREGATE COLLECT: empty field name in SortBy")
			}
			if s.Asc && s.Desc {
				return nil, fmt.Errorf("redis: FT.AGGREGATE COLLECT: ASC and DESC are mutually exclusive")
			}

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Set FieldsAll: true to collect all fields
  2. Populate Fields with at least one valid field name
  3. Guard the construction site so an empty field list falls back to FieldsAll

Example fix

// before
r := redis.NewCollectReducer(redis.CollectOptions{})
// after
r := redis.NewCollectReducer(redis.CollectOptions{FieldsAll: true})
Defensive patterns

Strategy: validation

Validate before calling

if !opts.FieldsAll && len(opts.Fields) == 0 {
    return fmt.Errorf("CollectOptions requires FieldsAll or a non-empty Fields list")
}

Prevention

When it happens

Trigger: NewCollectReducer with CollectOptions where FieldsAll is false and Fields is empty or nil; buildCollectArgs falls to the default branch and returns this error.

Common situations: Constructing CollectOptions with a dynamically built Fields slice that ended up empty; forgetting to set FieldsAll when no explicit fields are wanted.

Understand the failure class

Background: "Must pass :limit option" / "Missing required option" — required option errors explained — this error's family across 41 libraries.

Related errors


AI-assisted analysis of redis/go-redis@c5cad058c7 (2026-09-01). Data as JSON: /api/errors/46b488191fe311a9. Report an issue: GitHub.