{"record":{"id":"3db82ec59a51da76","repo":"apache/druid","slug":"cannot-operate-on-a-dimension-with-unknown-cardina-3db82e","errorCode":null,"errorMessage":"Cannot operate on a dimension with unknown cardinality","messagePattern":"Cannot operate on a dimension with unknown cardinality","errorType":"exception","errorClass":"UnsupportedOperationException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/topn/HeapBasedTopNAlgorithm.java","lineNumber":67,"sourceCode":"  public TopNParams makeInitParams(\n      final ColumnSelectorPlus<TopNColumnAggregatesProcessor> selectorPlus,\n      final Cursor cursor,\n      final CursorGranularizer granularizer\n  )\n  {\n    return new TopNParams(\n        selectorPlus,\n        cursor,\n        granularizer,\n        Integer.MAX_VALUE\n    );\n  }\n\n  @Override\n  protected Aggregator[][] makeDimValSelector(TopNParams params, int numProcessed, int numToProcess)\n  {\n    if (params.getCardinality() < 0) {\n      throw new UnsupportedOperationException(\"Cannot operate on a dimension with unknown cardinality\");\n    }\n    ColumnSelectorPlus<TopNColumnAggregatesProcessor> selectorPlus = params.getSelectorPlus();\n    return selectorPlus.getColumnSelectorStrategy().getRowSelector(query, params, cursorInspector);\n  }\n\n  @Override\n  protected Aggregator[][] updateDimValSelector(Aggregator[][] aggregators, int numProcessed, int numToProcess)\n  {\n    return aggregators;\n  }\n\n  @Override\n  protected TopNColumnAggregatesProcessor makeDimValAggregateStore(TopNParams params)\n  {\n    final ColumnSelectorPlus<TopNColumnAggregatesProcessor> selectorPlus = params.getSelectorPlus();\n    return selectorPlus.getColumnSelectorStrategy();\n  }\n","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/topn/HeapBasedTopNAlgorithm.java#L49-L85","documentation":"HeapBasedTopNAlgorithm.makeDimValSelector builds per-dimension-value arrays and therefore requires the dimension's cardinality to be known. If params.getCardinality() < 0 (selector has no dictionary), Druid throws UnsupportedOperationException(\"Cannot operate on a dimension with unknown cardinality\").","triggerScenarios":"TopN query using the heap-based algorithm (non-dictionary-ordering metric order, e.g. inverted numeric sort) on a dimension whose DimensionSelector reports unknown cardinality — expression dimensions, non-string columns, or selectors without dictionary support.","commonSituations":"TopN with descending/lexicographic-inverted sort on expression or lookup-wrapped dimensions, querying columns without dictionary encoding, custom segment formats that skip dictionary building.","solutions":["Switch the query to groupBy with an orderBys/limitSpec — no cardinality requirement","Use a dictionary-encoded string dimension (check segment metadata for the column)","Materialize the expression/lookup dimension as a physical column at ingestion","Choose a topN algorithm/sort combination compatible with the dimension's selector (e.g. default alphabetical)"],"exampleFix":"// before\n{ \"queryType\": \"topN\", \"dimension\": { \"type\": \"expression\", \"expression\": \"concat(x,'-sfx')\" }, \"metric\": { \"type\": \"inverted\", \"metric\": \"count\" } }\n// after\n{ \"queryType\": \"groupBy\", \"dimensions\": [{ \"type\": \"expression\", \"expression\": \"concat(x,'-sfx')\" }], \"limitSpec\": { \"type\": \"default\", \"limit\": 10, \"columns\": [{ \"dimension\": \"count\", \"direction\": \"descending\" }] } }","handlingStrategy":"fallback","validationCode":"int card = params.getCardinality();\nboolean safe = card >= 0;","typeGuard":"static boolean heapTopNSafe(TopNParams p) { return p != null && p.getCardinality() >= 0; }","tryCatchPattern":"try { return heapTopNRun(query); }\ncatch (UnsupportedOperationException e) {\n  if (e.getMessage().contains(\"unknown cardinality\")) { return groupByWithOrderBy(query); }\n  throw e;\n}","preventionTips":["Use groupBy+limitSpec for non-dictionary dimensions","Verify column dictionary encoding in segment metadata","Materialize expression dimensions at ingestion time"],"tags":["druid","topn","cardinality","heap-based"],"backgroundTag":"unsupported-operation","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"}