apache/druid · error · IllegalArgumentException

Cannot operate on a dimension with no dictionary

Error message

Cannot operate on a dimension with no dictionary

What it means

BaseTopNAlgorithm's BaseArrayProvider allocates arrays sized by the dimension's value cardinality. A negative cardinality means the DimensionSelector has no dictionary (cannot enumerate distinct values), so Druid throws IAE("Cannot operate on a dimension with no dictionary") instead of allocating against an undefined size.

Source

Thrown at processing/src/main/java/org/apache/druid/query/topn/BaseTopNAlgorithm.java:268

    private final TopNCursorInspector cursorInspector;

    public BaseArrayProvider(
        DimensionSelector dimSelector,
        TopNQuery query,
        TopNCursorInspector cursorInspector
    )
    {
      this.idLookup = dimSelector.idLookup();
      this.query = query;
      this.cursorInspector = cursorInspector;

      previousStop = null;
      ignoreAfterThreshold = false;
      ignoreFirstN = 0;
      keepOnlyN = dimSelector.getValueCardinality();

      if (keepOnlyN < 0) {
        throw new IAE("Cannot operate on a dimension with no dictionary");
      }
    }

    @Override
    public void skipTo(String previousStop)
    {
      ColumnCapabilities capabilities = cursorInspector.getColumnInspector()
                                                       .getColumnCapabilities(query.getDimensionSpec().getDimension());
      if (capabilities != null && capabilities.areDictionaryValuesSorted().isTrue()) {
        this.previousStop = previousStop;
      }
    }

    @Override
    public void ignoreAfterThreshold()
    {
      ignoreAfterThreshold = true;
    }

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Query a dictionary-encoded string dimension, or add it at ingestion time
  2. Replace topN with groupBy + limitSpec, which handles non-dictionary dimensions
  3. Remove the expression/extract dimension spec, or materialize it as a real column
  4. Check the segment metadata (GET /druid/v2/datasources/.../candidates) to confirm the column has a dictionary

Example fix

// before
{ "queryType": "topN", "dimension": { "type": "default", "dimension": "someNumericCol" } }
// after
{ "queryType": "groupBy", "dimensions": ["someNumericCol"], "limitSpec": { "type": "default", "limit": 10 } }
Defensive patterns

Strategy: fallback

Validate before calling

boolean safe = selector != null && selector.getValueCardinality() >= 0;

Type guard

static boolean supportsTopNArray(DimensionSelector s) { return s != null && s.getValueCardinality() >= 0; }

Try / catch

try { return defaultTopNRun(query); }
catch (IllegalArgumentException e) {
  if (e.getMessage().contains("no dictionary")) { return groupByFallback(query); }
  throw e;
}

Prevention

When it happens

Trigger: TopN query with the default (dictionary-based) topN algorithm on a dimension whose selector lacks a value dictionary: expression dimensions, columns without dictionary encoding, or selectors returning cardinality < 0.

Common situations: TopN on __time or numeric columns, querying non-string metric columns as dimensions, expression virtual columns, segments written by older ingestion that lacked dictionary encoding.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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