go-redis/redis · error

FT.SEARCH: ASC and DESC are mutually exclusive

Error message

FT.SEARCH: ASC and DESC are mutually exclusive

What it means

Returned by the FTSearchQuery query builder (search_commands.go:3376-3378): for any entry in options.SortBy, you cannot set both Asc:true and Desc:true on the same SortBy element. The library refuses to emit a contradictory SORTBY clause.

Source

Thrown at search_commands.go:3377

		}
		if options.Expander != "" {
			queryArgs = append(queryArgs, "EXPANDER", options.Expander)
		}
		if options.Scorer != "" {
			queryArgs = append(queryArgs, "SCORER", options.Scorer)
		}
		if options.ExplainScore {
			queryArgs = append(queryArgs, "EXPLAINSCORE")
		}
		if options.Payload != "" {
			queryArgs = append(queryArgs, "PAYLOAD", options.Payload)
		}
		if options.SortBy != nil {
			queryArgs = append(queryArgs, "SORTBY")
			for _, sortBy := range options.SortBy {
				queryArgs = append(queryArgs, sortBy.FieldName)
				if sortBy.Asc && sortBy.Desc {
					return nil, fmt.Errorf("FT.SEARCH: ASC and DESC are mutually exclusive")
				}
				if sortBy.Asc {
					queryArgs = append(queryArgs, "ASC")
				}
				if sortBy.Desc {
					queryArgs = append(queryArgs, "DESC")
				}
			}
			if options.SortByWithCount {
				queryArgs = append(queryArgs, "WITHCOUNT")
			}
		}
		if options.LimitOffset >= 0 && options.Limit > 0 {
			queryArgs = append(queryArgs, "LIMIT", options.LimitOffset, options.Limit)
		}
		if options.Params != nil {
			queryArgs = append(queryArgs, "PARAMS", len(options.Params)*2)
			for key, value := range options.Params {

View on GitHub (pinned to 36d97525cd)

Solutions

  1. Set exactly one of Asc or Desc per SortBy entry.
  2. Leave both false for the server default direction.
  3. Validate options.SortBy before calling FTSearchQuery.

Example fix

// before
q, err := redis.FTSearchQuery("*", &redis.FTSearchOptions{
    SortBy: []redis.FTSearchSortBy{{FieldName: "ts", Asc: true, Desc: true}},
})
// after
q, err := redis.FTSearchQuery("*", &redis.FTSearchOptions{
    SortBy: []redis.FTSearchSortBy{{FieldName: "ts", Asc: true}},
})
Defensive patterns

Strategy: validation

Validate before calling

// Reject contradictory SortBy entries before building the query.
for _, s := range opts.SortBy {
    if s.Asc && s.Desc {
        return fmt.Errorf("SortBy %q: pick ASC or DESC, not both", s.FieldName)
    }
}

Try / catch

q, err := redis.FTSearchQuery(qs, opts)
if err != nil && strings.Contains(err.Error(), "ASC and DESC are mutually exclusive") {
    // fix the SortBy entry that has both flags set
}

Prevention

When it happens

Trigger: Constructing a SearchQuery via FTSearchQuery with a redis.FTSearchSortBy{Asc: true, Desc: true, ...} entry.

Common situations: Copy-paste from another call where the opposite flag was set, or programmatic construction that defaulted both booleans true.

Related errors


AI-assisted analysis of go-redis/redis@36d97525cd (2026-08-06). Data as JSON: /data/errors/133677286359ffcb.json. Report an issue: GitHub.