{"id":"91e035c489bc326d","repo":"go-redis/redis","slug":"redis-invalid-timeseries-aggregator-at-index-d","errorCode":null,"errorMessage":"redis: invalid timeseries aggregator at index %d: Invalid (%d)","messagePattern":"redis: invalid timeseries aggregator at index (.+?): Invalid \\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"timeseries_commands.go","lineNumber":193,"sourceCode":"func formatAggregationArgs(aggregator Aggregator, aggregators []Aggregator) (string, int, error) {\n\tif aggregator != Invalid && len(aggregators) > 0 {\n\t\treturn \"\", 0, errTSAggregationConflict\n\t}\n\tif len(aggregators) == 0 {\n\t\tif aggregator == Invalid {\n\t\t\treturn \"\", 0, nil\n\t\t}\n\t\taggregationArg, err := formatAggregatorArg(aggregator)\n\t\tif err != nil {\n\t\t\treturn \"\", 0, err\n\t\t}\n\t\treturn aggregationArg, 1, nil\n\t}\n\n\tparts := make([]string, len(aggregators))\n\tfor i, agg := range aggregators {\n\t\tif agg == Invalid {\n\t\t\treturn \"\", 0, fmt.Errorf(\"redis: invalid timeseries aggregator at index %d: Invalid (%d)\", i, agg)\n\t\t}\n\t\taggregationArg, err := formatAggregatorArg(agg)\n\t\tif err != nil {\n\t\t\treturn \"\", 0, fmt.Errorf(\"redis: invalid timeseries aggregator at index %d: %d\", i, agg)\n\t\t}\n\t\tparts[i] = aggregationArg\n\t}\n\n\treturn strings.Join(parts, \",\"), len(parts), nil\n}\n\nfunc formatAggregatorArg(aggregator Aggregator) (string, error) {\n\taggregationArg := aggregator.String()\n\tif aggregationArg == \"\" {\n\t\treturn \"\", fmt.Errorf(\"redis: invalid timeseries aggregator: %d\", aggregator)\n\t}\n\treturn aggregationArg, nil\n}","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/timeseries_commands.go#L175-L211","documentation":"Returned by formatAggregationArgs when the Aggregators slice contains the zero-value Aggregator constant Invalid (0). This indicates the caller built a multi-aggregator spec but left one element unset. The message reports the slice index and the Invalid value so the offending element can be located.","triggerScenarios":"Calling TSRangeWithArgs/TSMRangeWithArgs/etc. with Aggregators containing an explicit redis.Invalid or an element of a pre-allocated slice that was never assigned a real aggregator (e.g. make([]redis.Aggregator, 3) with only two filled).","commonSituations":"Dynamically building an Aggregators slice with append/make where a branch fails to set a value, or copying from a source that uses 0 as a placeholder.","solutions":["Ensure every element of the Aggregators slice is a valid aggregator (Avg, Sum, Min, Max, Range, Count, First, Last, StdP, StdS, VarP, VarS, Twa, CountNaN, CountAll).","Filter out zero/Invalid values before passing the slice: aggregators = slices.DeleteFunc(aggregators, func(a redis.Aggregator) bool { return a == redis.Invalid }).","If appending conditionally, only append when the aggregator is valid."],"exampleFix":"// before\nopts := &redis.TSRangeOptions{Aggregators: []redis.Aggregator{redis.Avg, redis.Invalid}}\nclient.TSRangeWithArgs(ctx, key, 0, -1, opts)\n\n// after\nopts := &redis.TSRangeOptions{Aggregators: []redis.Aggregator{redis.Avg, redis.Sum}}\nclient.TSRangeWithArgs(ctx, key, 0, -1, opts)","handlingStrategy":"validation","validationCode":"func validAggregators(aggs []redis.Aggregator) error {\n    for i, a := range aggs {\n        if a == redis.Invalid {\n            return fmt.Errorf(\"aggregator at index %d is Invalid\", i)\n        }\n    }\n    return nil\n}","typeGuard":"func isValidAggregator(a redis.Aggregator) bool { return a != redis.Invalid && a <= redis.CountAll }","tryCatchPattern":null,"preventionTips":["Build Aggregators with append, never make([]redis.Aggregator, n) left partially filled.","Filter out redis.Invalid before passing the slice to TS commands.","Prefer named constants over casts."],"tags":["timeseries","aggregator","validation","invalid-enum"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}