{"record":{"id":"1a7afd41f4c2ded5","repo":"redis/go-redis","slug":"redis-ft-aggregate-collect-empty-field-name-in-s","errorCode":null,"errorMessage":"redis: FT.AGGREGATE COLLECT: empty field name in SortBy","messagePattern":"redis: FT\\.AGGREGATE COLLECT: empty field name in SortBy","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"search_collect.go","lineNumber":113,"sourceCode":"\t\t\t}\n\t\t\targs = append(args, ensureAtPrefix(f))\n\t\t}\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"redis: FT.AGGREGATE COLLECT requires FieldsAll or a non-empty Fields list\")\n\t}\n\n\t// DISTINCT (optional, forward-compatible).\n\tif o.Distinct {\n\t\targs = append(args, \"DISTINCT\")\n\t}\n\n\t// SORTBY (optional). sort_narg counts each field plus its optional\n\t// direction token.\n\tif len(o.SortBy) > 0 {\n\t\tsortTokens := make([]interface{}, 0, len(o.SortBy)*2)\n\t\tfor _, s := range o.SortBy {\n\t\t\tif strings.TrimLeft(s.FieldName, \"@\") == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"redis: FT.AGGREGATE COLLECT: empty field name in SortBy\")\n\t\t\t}\n\t\t\tif s.Asc && s.Desc {\n\t\t\t\treturn nil, fmt.Errorf(\"redis: FT.AGGREGATE COLLECT: ASC and DESC are mutually exclusive\")\n\t\t\t}\n\t\t\tsortTokens = append(sortTokens, ensureAtPrefix(s.FieldName))\n\t\t\tswitch {\n\t\t\tcase s.Desc:\n\t\t\t\tsortTokens = append(sortTokens, \"DESC\")\n\t\t\tcase s.Asc:\n\t\t\t\tsortTokens = append(sortTokens, \"ASC\")\n\t\t\t\t// neither set: ASC is the server default; emit nothing.\n\t\t\t}\n\t\t}\n\t\targs = append(args, \"SORTBY\", len(sortTokens))\n\t\targs = append(args, sortTokens...)\n\t}\n\n\t// LIMIT (optional).","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/redis/go-redis/blob/c5cad058c72f58370553b48566302303cf8a2e89/search_collect.go#L95-L131","documentation":"The COLLECT step's SORTBY list must contain non-empty field names. buildCollectArgs validates each SortBy entry after stripping any leading '@'; an entry that is empty or only '@' cannot be sorted on and aborts argument construction with this error.","triggerScenarios":"CollectOptions.SortBy containing an entry with FieldName set to \"\" or \"@\"; buildCollectArgs returns nil with this error while iterating the sort fields.","commonSituations":"Sort fields derived from request parameters where the sort key was omitted; copying option structs where FieldName was left at its zero value.","solutions":["Set FieldName to a real field name (e.g. \"@price\" or \"price\")","Filter out SortBy entries with empty FieldName before building","Validate sort configuration at load time"],"exampleFix":"// before\nopts := redis.CollectOptions{SortBy: []redis.CollectSortByField{{FieldName: \"\"}}}\n// after\nopts := redis.CollectOptions{SortBy: []redis.CollectSortByField{{FieldName: \"@price\"}}}","handlingStrategy":"validation","validationCode":"for _, s := range sortBy {\n    if strings.TrimLeft(s.FieldName, \"@\") == \"\" {\n        return fmt.Errorf(\"empty SortBy field name\")\n    }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reject empty sort keys at the API boundary","Use constants for known sort fields instead of free-form strings","Trim '@' and check non-empty for all external input"],"tags":["search","ft-aggregate","collect","validation"],"backgroundTag":"empty-required-field","analyzedSha":"c5cad058c72f58370553b48566302303cf8a2e89","analyzedAt":"2026-09-01T06:50:53.388Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}