redis/go-redis · error

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

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.

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.

Appendix: 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)