redis/go-redis · error

redis: FT.AGGREGATE COLLECT: ASC and DESC are mutually exclu

Error message

redis: FT.AGGREGATE COLLECT: ASC and DESC are mutually exclusive

What it means

Within a single COLLECT SORTBY field, ASC and DESC are mutually exclusive — a field sorts in one direction only. buildCollectArgs rejects entries with both Asc and Desc set to true rather than emitting an ambiguous SORTBY clause.

Source

Thrown at search_collect.go:116

	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")
			}
			sortTokens = append(sortTokens, ensureAtPrefix(s.FieldName))
			switch {
			case s.Desc:
				sortTokens = append(sortTokens, "DESC")
			case s.Asc:
				sortTokens = append(sortTokens, "ASC")
				// neither set: ASC is the server default; emit nothing.
			}
		}
		args = append(args, "SORTBY", len(sortTokens))
		args = append(args, sortTokens...)
	}

	// LIMIT (optional).
	if o.Limit != nil {
		args = append(args, "LIMIT", o.Limit.Offset, o.Limit.Count)
	}

View on GitHub (pinned to c5cad058c7)

Solutions

  1. Set exactly one of Asc or Desc (or neither, for the server default)
  2. Use a single direction enum/helper instead of two booleans
  3. Clear the opposite flag whenever one is set

Example fix

// before
f := redis.CollectSortByField{FieldName: "@price", Asc: true, Desc: true}
// after
f := redis.CollectSortByField{FieldName: "@price", Desc: true}
Defensive patterns

Strategy: validation

Validate before calling

if s.Asc && s.Desc {
    return fmt.Errorf("ASC and DESC are mutually exclusive for field %s", s.FieldName)
}

Prevention

When it happens

Trigger: A CollectOptions.SortBy entry with both Asc: true and Desc: true; buildCollectArgs returns this error during argument construction.

Common situations: Merging two config sources that each set a direction flag; copying a struct and forgetting to clear the old direction; a UI toggle that sets both booleans.

Related errors


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