{"record":{"id":"6198c610ee5ccc40","repo":"apache/druid","slug":"unknown-column-in-order-clause-s","errorCode":null,"errorMessage":"Unknown column in order clause[%s]","messagePattern":"Unknown column in order clause\\[(.+?)\\]","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/groupby/orderby/DefaultLimitSpec.java","lineNumber":294,"sourceCode":"    }\n\n    // Finally, apply offset after sorting and limiting.\n    if (isOffset()) {\n      return results -> sortAndLimitFn.apply(results).skip(offset);\n    } else {\n      return sortAndLimitFn;\n    }\n  }\n\n  private ColumnType getOrderByType(final OrderByColumnSpec columnSpec, final List<DimensionSpec> dimensions)\n  {\n    for (DimensionSpec dimSpec : dimensions) {\n      if (columnSpec.getDimension().equals(dimSpec.getOutputName())) {\n        return dimSpec.getOutputType();\n      }\n    }\n\n    throw new ISE(\"Unknown column in order clause[%s]\", columnSpec);\n  }\n\n  @Override\n  public LimitSpec filterColumns(Set<String> names)\n  {\n    return new DefaultLimitSpec(\n        columns.stream().filter(c -> names.contains(c.getDimension())).collect(Collectors.toList()),\n        offset,\n        limit\n    );\n  }\n\n  /**\n   * Returns a new DefaultLimitSpec identical to this one except for one difference: an offset parameter, if any, will\n   * be removed and added to the limit. This is designed for passing down queries to lower levels of the stack. Only\n   * the highest level should apply the offset parameter, and any pushed-down limits must be increased to accommodate\n   * the offset.\n   */","sourceCodeStart":276,"sourceCodeEnd":312,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/groupby/orderby/DefaultLimitSpec.java#L276-L312","documentation":"DefaultLimitSpec.getOrderByType resolves the output type of a column in the ORDER BY / limit clause by looking it up among the query's aggregators, post-aggregators, and dimension specs. If the ordering column matches none of them, an IllegalStateException is thrown — meaning the limit spec references a column the query does not actually produce.","triggerScenarios":"A DefaultLimitSpec (limit/orderBy in a groupBy or topN query) contains an OrderByColumnSpec whose name matches no dimension outputName, aggregator name, or post-aggregator name; getOrderByType is called during planning (e.g. via columnType).","commonSituations":"Typos in orderBy column names; dashboard/UI sending sort keys for columns removed from the query; renaming a dimension outputName without updating the limit spec; nested queries where the sort column only exists in the inner query.","solutions":["Make the orderBy column name exactly match a dimension outputName, aggregator, or post-aggregator in the same query spec.","Add the referenced column as a dimension/aggregator or remove it from the limit spec.","If sorting should happen after an outer query, restructure with a nested query where each layer's limit spec references only its own outputs."],"exampleFix":"// before\n\"limitSpec\":{\"type\":\"default\",\"columns\":[{\"dimension\":\"user_name\"}]}\n// but dimension is {\"dimension\":\"user\",\"outputName\":\"user\"}\n// after\n\"limitSpec\":{\"type\":\"default\",\"columns\":[{\"dimension\":\"user\"}]}","handlingStrategy":"validation","validationCode":"Set<String> outputs = new HashSet<>();\ndimensions.forEach(d -> outputs.add(d.getOutputName()));\naggregators.forEach(a -> outputs.add(a.getName()));\npostAggregators.forEach(p -> outputs.add(p.getName()));\nfor (OrderByColumnSpec c : limitSpec.getColumns()) {\n  if (!outputs.contains(c.getDimension())) throw new IllegalArgumentException(\"Unknown order-by column: \" + c.getDimension());\n}","typeGuard":null,"tryCatchPattern":"try {\n  return engine.plan(query);\n} catch (IllegalStateException e) {\n  if (e.getMessage() != null && e.getMessage().contains(\"Unknown column in order clause\")) {\n    throw new QueryValidationException(e.getMessage(), e);\n  }\n  throw e;\n}","preventionTips":["Validate limitSpec columns against query outputs before submitting","Use exact outputName (not input fieldName) in order-by specs","When renaming dimension outputName, update all limit specs referencing it","Catch ISE at plan time and translate to a user-facing validation error"],"tags":["druid","group-by","limit-spec","ordering"],"backgroundTag":"resource-not-found","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}