{"record":{"id":"3b1adc94c28699e4","repo":"apache/druid","slug":"when-forcing-limit-push-down-a-limit-spec-must-be","errorCode":null,"errorMessage":"When forcing limit push down, a limit spec must be provided.","messagePattern":"When forcing limit push down, a limit spec must be provided\\.","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/groupby/GroupByQuery.java","lineNumber":506,"sourceCode":"\n    return Ordering.from(\n        (lhs, rhs) -> {\n          if (lhs instanceof ResultRow) {\n            return rowOrdering.compare((ResultRow) lhs, (ResultRow) rhs);\n          } else {\n            //noinspection unchecked (Probably bySegment queries; see BySegmentQueryRunner for details)\n            return ((Ordering) Comparators.naturalNullsFirst()).compare(lhs, rhs);\n          }\n        }\n    );\n  }\n\n  private boolean validateAndGetForceLimitPushDown()\n  {\n    final boolean forcePushDown = context().getBoolean(GroupByQueryConfig.CTX_KEY_FORCE_LIMIT_PUSH_DOWN, false);\n    if (forcePushDown) {\n      if (!(limitSpec instanceof DefaultLimitSpec)) {\n        throw new IAE(\"When forcing limit push down, a limit spec must be provided.\");\n      }\n\n      if (!((DefaultLimitSpec) limitSpec).isLimited()) {\n        throw new IAE(\"When forcing limit push down, the provided limit spec must have a limit.\");\n      }\n\n      if (havingSpec != null) {\n        throw new IAE(\"Cannot force limit push down when a having spec is present.\");\n      }\n\n      for (OrderByColumnSpec orderBySpec : ((DefaultLimitSpec) limitSpec).getColumns()) {\n        if (OrderByColumnSpec.getPostAggIndexForOrderBy(orderBySpec, postAggregatorSpecs) > -1) {\n          throw new UnsupportedOperationException(\"Limit push down when sorting by a post aggregator is not supported.\");\n        }\n      }\n    }\n    return forcePushDown;\n  }","sourceCodeStart":488,"sourceCodeEnd":524,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/groupby/GroupByQuery.java#L488-L524","documentation":"When the query context forces limit push down (forceLimitPushDown=true), GroupByQuery requires a DefaultLimitSpec so limits can be pushed into the segment-level processing. validateAndGetForceLimitPushDown throws IAE if the limitSpec is missing or of the wrong type.","triggerScenarios":"Setting context key forceLimitPushDown=true while limitSpec is null or is a non-DefaultLimitSpec implementation (e.g. NoopLimitSpec).","commonSituations":"Users enabling forceLimitPushDown in query context for performance without specifying a limit; programmatic query builders that omit limitSpec; queries where SQL planner strips the limit.","solutions":["Provide a DefaultLimitSpec with columns and a limit in the query when forceLimitPushDown is enabled.","Remove the forceLimitPushDown context flag so the query runs without forced push down.","Verify the limitSpec is DefaultLimitSpec (cast-check) before enabling the flag in query-building code."],"exampleFix":"// before\ncontext.put(\"forceLimitPushDown\", true); // query has no limitSpec\n// after\ncontext.put(\"forceLimitPushDown\", true);\nquery = query.withLimitSpec(new DefaultLimitSpec(ImmutableList.of(new OrderByColumnSpec(\"dim\", ASC)), 100));","handlingStrategy":"validation","validationCode":"boolean ok = !forcePushDown || (query.getLimitSpec() instanceof DefaultLimitSpec);","typeGuard":"boolean hasDefaultLimitSpec = query.getLimitSpec() instanceof DefaultLimitSpec;","tryCatchPattern":"try { query.validateAndGetForceLimitPushDown(); } catch (IllegalArgumentException e) { /* add limit spec or drop the flag */ }","preventionTips":["Only set forceLimitPushDown when a DefaultLimitSpec exists","Inspect effective query context before enabling push-down flags","Let the engine choose push down instead of forcing it"],"tags":["druid","groupby","limit-pushdown","query-context"],"backgroundTag":"missing-required-argument","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"}