{"record":{"id":"c8d64a0d5c0905f4","repo":"apache/druid","slug":"can-t-find-the-topn-metric","errorCode":null,"errorMessage":"Can't find the topN metric","messagePattern":"Can't find the topN metric","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/query/topn/AggregateTopNMetricFirstAlgorithm.java","lineNumber":83,"sourceCode":"  public TopNParams makeInitParams(ColumnSelectorPlus selectorPlus, Cursor cursor, CursorGranularizer granularizer)\n  {\n    return new TopNParams(selectorPlus, cursor, granularizer, Integer.MAX_VALUE);\n  }\n\n  @Override\n  public void run(\n      TopNParams params,\n      TopNResultBuilder resultBuilder,\n      int[] ints,\n      @Nullable TopNQueryMetrics queryMetrics\n  )\n  {\n    final String metric = query.getTopNMetricSpec().getMetricName(query.getDimensionSpec());\n    Pair<List<AggregatorFactory>, List<PostAggregator>> condensedAggPostAggPair =\n        AggregatorUtil.condensedAggregators(query.getAggregatorSpecs(), query.getPostAggregatorSpecs(), metric);\n\n    if (condensedAggPostAggPair.lhs.isEmpty() && condensedAggPostAggPair.rhs.isEmpty()) {\n      throw new ISE(\"Can't find the topN metric\");\n    }\n    // Run topN for only a single metric\n    TopNQuery singleMetricQuery = new TopNQueryBuilder(query)\n        .aggregators(condensedAggPostAggPair.lhs)\n        .postAggregators(condensedAggPostAggPair.rhs)\n        .build();\n    final TopNResultBuilder singleMetricResultBuilder = BaseTopNAlgorithm.makeResultBuilder(params, singleMetricQuery);\n\n    PooledTopNAlgorithm singleMetricAlgo = new PooledTopNAlgorithm(singleMetricQuery, cursorInspector, bufferPool);\n    PooledTopNAlgorithm.PooledTopNParams singleMetricParam = null;\n    int[] dimValSelector;\n    try {\n      singleMetricParam = singleMetricAlgo.makeInitParams(params.getSelectorPlus(), params.getCursor(), params.getGranularizer());\n      singleMetricAlgo.run(\n          singleMetricParam,\n          singleMetricResultBuilder,\n          null,\n          null // Don't collect metrics during the preparation run.","sourceCodeStart":65,"sourceCodeEnd":101,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/query/topn/AggregateTopNMetricFirstAlgorithm.java#L65-L101","documentation":"AggregateTopNMetricFirstAlgorithm runs topN for a single metric by condensing the query's aggregators/postAggregators down to those the topN metric depends on. If after condensing both lists are empty, the requested topN metric is not produced by any aggregator, so Druid throws ISE(\"Can't find the topN metric\").","triggerScenarios":"A TopNQuery whose topNMetricSpec.getMetricName() refers to a name absent from both aggregatorSpecs and postAggregatorSpecs — e.g. a typo in the metric name, or a metric produced only by a filtered/aggregator chain that condensing removed.","commonSituations":"Typos in orderBySpec metric names, referencing a post-aggregator output whose inputs were pruned, programmatically built queries reusing stale metric names after schema changes.","solutions":["Make the topN metric name exactly match an aggregator output or post-aggregator name in the query","Add the missing aggregator/postAggregator to the query so it produces the metric","Simplify to a direct aggregator output metric (e.g. use the base 'metric' the post-agg derives from)","Print AggregatorUtil.condensedAggregators inputs/outputs when debugging programmatic query builders"],"exampleFix":"// before\nnew TopNQueryBuilder().metric(\"clickt\").aggregators(new CountAggregatorFactory(\"count\"))...\n// after\nnew TopNQueryBuilder().metric(\"count\").aggregators(new CountAggregatorFactory(\"count\"))...","handlingStrategy":"validation","validationCode":"Set<String> produced = new HashSet<>();\nquery.getAggregatorSpecs().forEach(a -> produced.add(a.getName()));\nquery.getPostAggregatorSpecs().forEach(p -> produced.add(p.getName()));\nboolean safe = produced.contains(query.getTopNMetricSpec().getMetricName(query.getDimensionSpec()));","typeGuard":"static boolean metricIsProduced(TopNQuery q) {\n  String m = q.getTopNMetricSpec().getMetricName(q.getDimensionSpec());\n  return q.getAggregatorSpecs().stream().anyMatch(a -> a.getName().equals(m))\n      || q.getPostAggregatorSpecs().stream().anyMatch(p -> p.getName().equals(m));\n}","tryCatchPattern":"try { return algo.run(params, builder, op); }\ncatch (IllegalStateException e) { if (e.getMessage().equals(\"Can't find the topN metric\")) { throw new InvalidQueryException(e); } throw e; }","preventionTips":["Validate topN metric names against aggregators before submitting","Avoid referencing post-aggregators whose inputs were pruned","Keep query builder helpers in sync with schema changes"],"tags":["druid","topn","metric-not-found","query-config"],"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"}