{"record":{"id":"f7b612dafd142693","repo":"redis/jedis","slug":"excludeempty-is-not-allowed-with-groupby","errorCode":null,"errorMessage":"EXCLUDEEMPTY is not allowed with GROUPBY.","messagePattern":"EXCLUDEEMPTY is not allowed with GROUPBY\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"src/main/java/redis/clients/jedis/timeseries/TSMRangeParams.java","lineNumber":251,"sourceCode":"    this.filters = filters;\n    return this;\n  }\n\n  public TSMRangeParams groupBy(String label, String reduce) {\n    this.groupByLabel = label;\n    this.groupByReduce = reduce;\n    return this;\n  }\n\n  @Override\n  public void addParams(CommandArguments args) {\n\n    if (filters == null) {\n      throw new IllegalArgumentException(\"FILTER arguments must be set.\");\n    }\n\n    if (excludeEmpty && groupByLabel != null && groupByReduce != null) {\n      throw new IllegalArgumentException(\"EXCLUDEEMPTY is not allowed with GROUPBY.\");\n    }\n\n    if (fromTimestamp == null) {\n      args.add(MINUS);\n    } else {\n      args.add(toByteArray(fromTimestamp));\n    }\n\n    if (toTimestamp == null) {\n      args.add(PLUS);\n    } else {\n      args.add(toByteArray(toTimestamp));\n    }\n\n    if (latest) {\n      args.add(LATEST);\n    }\n","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/redis/jedis/blob/6dac31d4c224fb3257c216f3985340c6f500cdcb/src/main/java/redis/clients/jedis/timeseries/TSMRangeParams.java#L233-L269","documentation":"TSMRangeParams.addParams rejects combining EXCLUDEEMPTY with GROUPBY: when excludeEmpty is true and both groupByLabel and groupByReduce are set, it throws IllegalArgumentException(\"EXCLUDEEMPTY is not allowed with GROUPBY.\"). RedisTimeSeries does not permit this flag combination in TS.MRANGE, so the client blocks it before sending the command.","triggerScenarios":"Calling both excludeEmpty()/setExcludeEmpty(true) and groupBy(label, reduce) (e.g. groupBy(\"region\", Reduce.SUM)) on the same TSMRangeParams instance and then executing the query.","commonSituations":"Cumulative builder code where a base params object gets excludeEmpty from one config option and GROUPBY from another, both enabled; copy-pasting example queries that each use one of the features; flags toggled by different user preferences.","solutions":["Remove excludeEmpty() when grouping; pre-filter empty series or post-process results to drop empty buckets instead.","Keep EXCLUDEEMPTY only for plain (non-GROUPBY) filtered queries.","Add mutual-exclusion validation in your config/UI so both options cannot be enabled simultaneously."],"exampleFix":"// before\nparams.excludeEmpty().groupBy(\"region\", Reduce.SUM); // throws\n// after\nparams.groupBy(\"region\", Reduce.SUM); // drop EXCLUDEEMPTY when using GROUPBY","handlingStrategy":"validation","validationCode":"if (useExcludeEmpty && groupByLabel != null) {\n  throw new IllegalArgumentException(\"EXCLUDEEMPTY cannot be combined with GROUPBY\");\n}","typeGuard":"boolean isCompatible(TSMRangeParams p, boolean excludeEmpty, String groupByLabel, Reduce reduce) {\n  return !(excludeEmpty && groupByLabel != null && reduce != null);\n}","tryCatchPattern":"try {\n  jedis.ts.mrange(params);\n} catch (IllegalArgumentException e) {\n  if (e.getMessage().contains(\"EXCLUDEEMPTY\")) {\n    log.warn(\"Dropping EXCLUDEEMPTY because GROUPBY is set\");\n  } else throw e;\n}","preventionTips":["Treat EXCLUDEEMPTY and GROUPBY as mutually exclusive when building params.","Centralize TSMRangeParams construction so both flags cannot be set from independent config options.","Filter out empty buckets in application code after GROUPBY instead of using EXCLUDEEMPTY."],"tags":["java","timeseries","mutually-exclusive","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"6dac31d4c224fb3257c216f3985340c6f500cdcb","analyzedAt":"2026-09-08T04:55:01.204Z","contentChangedAt":"2026-09-08T04:55:01.204Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}