{"record":{"id":"bfbddfa0460adc1c","repo":"apache/druid","slug":"subqueries-must-be-of-type-group-by","errorCode":null,"errorMessage":"Subqueries must be of type 'group by'","messagePattern":"Subqueries must be of type 'group by'","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChest.java","lineNumber":280,"sourceCode":"        // Unlike withOverriddenContext's normal behavior, we want keys present in the subquery to win.\n        final Map<String, Object> subqueryContext = new TreeMap<>();\n        if (query.getContext() != null) {\n          for (Map.Entry<String, Object> entry : query.getContext().entrySet()) {\n            if (entry.getValue() != null) {\n              subqueryContext.put(entry.getKey(), entry.getValue());\n            }\n          }\n        }\n        if (((QueryDataSource) dataSource).getQuery().getContext() != null) {\n          subqueryContext.putAll(((QueryDataSource) dataSource).getQuery().getContext());\n        }\n        subqueryContext.put(GroupByQuery.CTX_KEY_SORT_BY_DIMS_FIRST, false);\n        subquery = (GroupByQuery) ((QueryDataSource) dataSource).getQuery().withOverriddenContext(subqueryContext);\n\n        closer.register(() -> groupByStatsProvider.closeQuery(subquery.context().getQueryResourceId()));\n      }\n      catch (ClassCastException e) {\n        throw new UnsupportedOperationException(\"Subqueries must be of type 'group by'\");\n      }\n\n      final Sequence<ResultRow> subqueryResult = mergeGroupByResults(\n          subquery,\n          resource,\n          runner,\n          context,\n          closer,\n          perQueryStats\n      );\n\n      final Sequence<ResultRow> finalizingResults = finalizeSubqueryResults(subqueryResult, subquery);\n\n      if (query.getSubtotalsSpec() != null) {\n        return groupingEngine.processSubtotalsSpec(\n            query,\n            resource,\n            groupingEngine.processSubqueryResult(","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/groupby/GroupByQueryQueryToolChest.java#L262-L298","documentation":"mergeGroupByResultsWithoutPushDown expects the DataSource of the subquery being merged to be a QueryDataSource wrapping a GroupByQuery. When the cast fails (the wrapped query is not a GroupByQuery), an UnsupportedOperationException 'Subqueries must be of type \\\"group by\\\"' is thrown.","triggerScenarios":"Running a group-by with a subquery whose dataSource wraps a non-group-by query (e.g. a timeseries, topN, or scan query) such that ((QueryDataSource)dataSource).getQuery() cannot be cast to GroupByQuery.","commonSituations":"Nested native queries mixing engines/query types (timeseries inside groupBy); SQL-generated plans where the planner produced an unsupported nesting shape on older Druid versions; hand-built multi-level native queries.","solutions":["Rewrite the inner query as a groupBy query (groupBy can express most timeseries/topN shapes)","Flatten the query into a single-level query or compute the inner query separately and use its results (e.g. via a join or inline datasource)","Upgrade Druid — newer versions support more subquery types via QueryDataSource handling in the group-by engine"],"exampleFix":"// before\nDataSource sub = new QueryDataSource(Druids.newTimeseriesQueryBuilder()...build());\n// after\nDataSource sub = new QueryDataSource(Druids.newTimeseriesQueryBuilder()...build().toGroupByQuery()); // or use a groupBy builder directly","handlingStrategy":"type-guard","validationCode":"if (dataSource instanceof QueryDataSource && !(((QueryDataSource) dataSource).getQuery() instanceof GroupByQuery)) { throw new UnsupportedOperationException(\"Inner query must be a groupBy\"); }","typeGuard":"boolean isGroupBySubquery(DataSource ds) { return ds instanceof QueryDataSource && ((QueryDataSource) ds).getQuery() instanceof GroupByQuery; }","tryCatchPattern":"try { mergeGroupByResultsWithoutPushDown(...); } catch (UnsupportedOperationException e) { /* run inner query separately or rewrite plan */ }","preventionTips":["Only nest groupBy queries inside groupBy subqueries","Convert timeseries/topN inner queries to groupBy equivalents before nesting"],"tags":["groupby","subquery","unsupported-operation"],"backgroundTag":"incompatible-source-type","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"}