{"id":"f2b9ad9fb3146de1","repo":"go-redis/redis","slug":"redis-invalid-timeseries-aggregator-d","errorCode":null,"errorMessage":"redis: invalid timeseries aggregator: %d","messagePattern":"redis: invalid timeseries aggregator: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"timeseries_commands.go","lineNumber":208,"sourceCode":"\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}\n\ntype TSRangeOptions struct {\n\tLatest        bool\n\tFilterByTS    []int\n\tFilterByValue []int\n\tCount         int\n\tAlign         interface{}\n\t// Deprecated: use Aggregators instead.\n\tAggregator      Aggregator\n\tAggregators     []Aggregator\n\tBucketDuration  int\n\tBucketTimestamp interface{}\n\tEmpty           bool\n}\n","sourceCodeStart":190,"sourceCodeEnd":226,"githubUrl":"https://github.com/go-redis/redis/blob/36d97525cd8076aed67cddf54778e9ea84550929/timeseries_commands.go#L190-L226","documentation":"Returned by formatAggregatorArg when aggregator.String() returns the empty string, which occurs for any Aggregator value not covered by the switch (i.e. the Invalid zero value or an out-of-range cast). This is the single-aggregator code path in formatAggregationArgs and the shared helper.","triggerScenarios":"Passing a single Aggregator (the deprecated Aggregator field) that is either redis.Invalid or an out-of-range cast value such as redis.Aggregator(50).","commonSituations":"Default zero-value Aggregator left in TSOptions/TSRangeOptions when the caller intended to set one, or an integer cast from external data without validation.","solutions":["Set the Aggregator field to a valid named constant (redis.Avg, redis.Sum, etc.).","Prefer the Aggregators slice over the deprecated single Aggregator field.","Bounds-check any cast aggregator against [redis.Avg, redis.CountAll] before use."],"exampleFix":"// before\nopts := &redis.TSRangeOptions{Aggregator: redis.Aggregator(0)} // Invalid\nclient.TSRangeWithArgs(ctx, key, 0, -1, opts)\n\n// after\nopts := &redis.TSRangeOptions{Aggregators: []redis.Aggregator{redis.Avg}}\nclient.TSRangeWithArgs(ctx, key, 0, -1, opts)","handlingStrategy":"validation","validationCode":"func validSingleAggregator(a redis.Aggregator) error {\n    if a == redis.Invalid || a > redis.CountAll {\n        return fmt.Errorf(\"aggregator %d is not valid\", a)\n    }\n    return nil\n}","typeGuard":"func isValidAggregator(a redis.Aggregator) bool { return a != redis.Invalid && a <= redis.CountAll }","tryCatchPattern":null,"preventionTips":["Migrate from the deprecated single Aggregator field to the Aggregators slice.","Always set the aggregator explicitly rather than relying on the zero value.","Validate cast values from external sources before assignment."],"tags":["timeseries","aggregator","validation","enum-out-of-range","deprecated"],"analyzedSha":"36d97525cd8076aed67cddf54778e9ea84550929","analyzedAt":"2026-08-06T01:08:27.376Z","schemaVersion":2}