apache/druid · error · IllegalStateException

Can't find the topN metric

Error message

Can't find the topN metric

What it means

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").

Source

Thrown at processing/src/main/java/org/apache/druid/query/topn/AggregateTopNMetricFirstAlgorithm.java:83

  public TopNParams makeInitParams(ColumnSelectorPlus selectorPlus, Cursor cursor, CursorGranularizer granularizer)
  {
    return new TopNParams(selectorPlus, cursor, granularizer, Integer.MAX_VALUE);
  }

  @Override
  public void run(
      TopNParams params,
      TopNResultBuilder resultBuilder,
      int[] ints,
      @Nullable TopNQueryMetrics queryMetrics
  )
  {
    final String metric = query.getTopNMetricSpec().getMetricName(query.getDimensionSpec());
    Pair<List<AggregatorFactory>, List<PostAggregator>> condensedAggPostAggPair =
        AggregatorUtil.condensedAggregators(query.getAggregatorSpecs(), query.getPostAggregatorSpecs(), metric);

    if (condensedAggPostAggPair.lhs.isEmpty() && condensedAggPostAggPair.rhs.isEmpty()) {
      throw new ISE("Can't find the topN metric");
    }
    // Run topN for only a single metric
    TopNQuery singleMetricQuery = new TopNQueryBuilder(query)
        .aggregators(condensedAggPostAggPair.lhs)
        .postAggregators(condensedAggPostAggPair.rhs)
        .build();
    final TopNResultBuilder singleMetricResultBuilder = BaseTopNAlgorithm.makeResultBuilder(params, singleMetricQuery);

    PooledTopNAlgorithm singleMetricAlgo = new PooledTopNAlgorithm(singleMetricQuery, cursorInspector, bufferPool);
    PooledTopNAlgorithm.PooledTopNParams singleMetricParam = null;
    int[] dimValSelector;
    try {
      singleMetricParam = singleMetricAlgo.makeInitParams(params.getSelectorPlus(), params.getCursor(), params.getGranularizer());
      singleMetricAlgo.run(
          singleMetricParam,
          singleMetricResultBuilder,
          null,
          null // Don't collect metrics during the preparation run.

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Make the topN metric name exactly match an aggregator output or post-aggregator name in the query
  2. Add the missing aggregator/postAggregator to the query so it produces the metric
  3. Simplify to a direct aggregator output metric (e.g. use the base 'metric' the post-agg derives from)
  4. Print AggregatorUtil.condensedAggregators inputs/outputs when debugging programmatic query builders

Example fix

// before
new TopNQueryBuilder().metric("clickt").aggregators(new CountAggregatorFactory("count"))...
// after
new TopNQueryBuilder().metric("count").aggregators(new CountAggregatorFactory("count"))...
Defensive patterns

Strategy: validation

Validate before calling

Set<String> produced = new HashSet<>();
query.getAggregatorSpecs().forEach(a -> produced.add(a.getName()));
query.getPostAggregatorSpecs().forEach(p -> produced.add(p.getName()));
boolean safe = produced.contains(query.getTopNMetricSpec().getMetricName(query.getDimensionSpec()));

Type guard

static boolean metricIsProduced(TopNQuery q) {
  String m = q.getTopNMetricSpec().getMetricName(q.getDimensionSpec());
  return q.getAggregatorSpecs().stream().anyMatch(a -> a.getName().equals(m))
      || q.getPostAggregatorSpecs().stream().anyMatch(p -> p.getName().equals(m));
}

Try / catch

try { return algo.run(params, builder, op); }
catch (IllegalStateException e) { if (e.getMessage().equals("Can't find the topN metric")) { throw new InvalidQueryException(e); } throw e; }

Prevention

When it happens

Trigger: 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.

Common situations: Typos in orderBySpec metric names, referencing a post-aggregator output whose inputs were pruned, programmatically built queries reusing stale metric names after schema changes.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/c8d64a0d5c0905f4. Report an issue: GitHub.