apache/druid · error · IllegalStateException

Column[ ] is multi-value, do not ask for a single-value…

Error message

Column[%s] is multi-value, do not ask for a single-value selector

What it means

Vectorized single-value dimension selectors assume each row contributes exactly one value. If the underlying column can hold multiple values (hasMultipleValues().isMaybeTrue()), the factory throws this ISE because silently taking the first value would change query semantics.

Solutions

  1. Use a multi-value dimension selector or MV/ARRAY-aware aggregators for this column
  2. Force a consistent column type by re-ingesting with an explicit dimensionsSpec (single-value string)
  3. Query with ARRAY functions or flatten the MV column into separate rows at ingest
  4. Disable vectorization as an interim workaround

Example fix

// before
factory.makeSingleValueDimensionSelector(DefaultDimensionSpec.of("mvCol"));
// after
factory.makeMultiValueDimensionSelector(DefaultDimensionSpec.of("mvCol"));
Defensive patterns

Strategy: validation

Validate before calling

// before requesting single-value selector
if (holder.getCapabilities().hasMultipleValues().isMaybeTrue()) {
  useMultiValueSelector();
} else {
  useSingleValueSelector();
}

Type guard

boolean definitelySingleValue = !caps.hasMultipleValues().isMaybeTrue();

Try / catch

try { sel = factory.makeSingleValueDimensionSelector(spec); } catch (IllegalStateException e) { sel = factory.makeMultiValueDimensionSelector(spec); }

Prevention

When it happens

Trigger: makeSingleValueDimensionSelector called on a column that is (or may be, in some segments) multi-value string; heterogeneous segments where a column is MV in one segment and SV in another.

Common situations: Schema drift after changing ingestion from single to multi-value; query planner choosing single-value path based on a different segment's schema; extension code building selectors directly.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at processing/src/main/java/org/apache/druid/segment/vector/QueryableIndexVectorColumnSelectorFactory.java:147

    }

    Function<DimensionSpec, SingleValueDimensionVectorSelector> mappingFunction = spec -> {
      final String name = spec.getDimension();
      if (virtualColumns.exists(name)) {
        return virtualColumns.makeSingleValueDimensionVectorSelector(dimensionSpec, this, columnSelector, offset);
      }

      final ColumnHolder holder = columnSelector.getColumnHolder(name);
      if (holder == null
          || !holder.getCapabilities().isDictionaryEncoded().isTrue()
          || !holder.getCapabilities().is(ValueType.STRING)) {
        // Asking for a single-value dimension selector on a non-string column gets you a bunch of nulls.
        return NilVectorSelector.create(offset);
      }

      if (holder.getCapabilities().hasMultipleValues().isMaybeTrue()) {
        // Asking for a single-value dimension selector on a multi-value column gets you an error.
        throw new ISE("Column[%s] is multi-value, do not ask for a single-value selector", name);
      }

      final BaseColumn column = (BaseColumn) holder.getColumn(); // if not VirtualColumn, must be BaseColumn.
      final SingleValueDimensionVectorSelector selector;
      if (column instanceof DictionaryEncodedColumn) {
        selector = ((DictionaryEncodedColumn<?>) column).makeSingleValueDimensionVectorSelector(offset);
      } else {
        final NestedVectorColumnSelectorFactory nestedColumnSelectorFactory =
            column.as(NestedVectorColumnSelectorFactory.class);
        if (nestedColumnSelectorFactory != null) {
          selector = nestedColumnSelectorFactory.makeSingleValueDimensionVectorSelector(List.of(), this, offset);
        } else {
          selector = NilVectorSelector.create(offset);
        }
      }

      return spec.decorate(selector);
    };

View on GitHub (pinned to 9b90983fd2)