{"record":{"id":"6466dea928044cb5","repo":"apache/druid","slug":"ambiguous-build-limit-s-or-columnspecs-s-alre","errorCode":null,"errorMessage":"Ambiguous build, limit[%s] or columnSpecs[%s] already set.","messagePattern":"Ambiguous build, limit\\[(.+?)\\] or columnSpecs\\[(.+?)\\] already set\\.","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/groupby/GroupByQuery.java","lineNumber":1132,"sourceCode":"    {\n      Preconditions.checkNotNull(limitSpec);\n      ensureFluentLimitsNotSet();\n      this.limitSpec = limitSpec;\n      this.postProcessingFn = null;\n      return this;\n    }\n\n    private void ensureExplicitLimitSpecNotSet()\n    {\n      if (limitSpec != null) {\n        throw new ISE(\"Ambiguous build, limitSpec[%s] already set\", limitSpec);\n      }\n    }\n\n    private void ensureFluentLimitsNotSet()\n    {\n      if (!(limit == Integer.MAX_VALUE && orderByColumnSpecs.isEmpty())) {\n        throw new ISE(\"Ambiguous build, limit[%s] or columnSpecs[%s] already set.\", limit, orderByColumnSpecs);\n      }\n    }\n\n    public Builder setQuerySegmentSpec(QuerySegmentSpec querySegmentSpec)\n    {\n      this.querySegmentSpec = querySegmentSpec;\n      return this;\n    }\n\n    public Builder setDimFilter(@Nullable DimFilter dimFilter)\n    {\n      this.dimFilter = dimFilter;\n      return this;\n    }\n\n    public Builder setGranularity(Granularity granularity)\n    {\n      this.granularity = granularity;","sourceCodeStart":1114,"sourceCodeEnd":1150,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/groupby/GroupByQuery.java#L1114-L1150","documentation":"Inverse of the explicit-limitSpec check: ensureFluentLimitsNotSet throws ISE when fluent limit APIs (setLimit/addOrderByColumnSpec) were already used and an explicit limitSpec is then set on the same Builder, because the resulting limit configuration would be ambiguous.","triggerScenarios":"Calling Builder.setLimit(...) or addOrderByColumnSpec(...) and then setLimitSpec(...) on the same builder instance.","commonSituations":"Programmatic query building that first applies default sorting then a caller-supplied limitSpec; framework code layering limitSpec onto pre-configured builders; deserialization edge cases.","solutions":["Remove one of the two limit definitions — keep either the fluent limit or the explicit limitSpec","Reset/rebuild the builder if limits from a previous stage should be discarded","Check builder state (limit != Integer.MAX_VALUE or non-empty orderByColumnSpecs) before calling setLimitSpec"],"exampleFix":"// before\nbuilder.setLimit(10).addOrderByColumnSpec(new OrderByColumnSpec(\"dim\", ASC)).setLimitSpec(spec);\n// after\nbuilder.setLimitSpec(spec); // drop the fluent limit calls","handlingStrategy":"validation","validationCode":"if (limit != Integer.MAX_VALUE || !orderByColumnSpecs.isEmpty()) { /* fluent limits set — do not call setLimitSpec */ }","typeGuard":"null","tryCatchPattern":"try { builder.setLimitSpec(spec); } catch (IllegalStateException e) { if (e.getMessage().contains(\"columnSpecs\")) { /* clear fluent limits first */ } throw e; }","preventionTips":["Set the limitSpec before any fluent limit calls, or not at all","Track builder limit state explicitly in wrapper classes"],"tags":["groupby","builder","ambiguous-build"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}