apache/druid · error · IllegalStateException
Only constant and single input string expressions currently…
Error message
Only constant and single input string expressions currently support dictionary encoded selectors
What it means
Dictionary-encoded (single-value dimension) vector selectors for expression virtual columns are only implemented for constant expressions and single-input scalar string expressions. Any other expression plan (multi-input, numeric output) hitting this path throws IllegalStateException, since only deferred-evaluation string selectors exist for this code path.
Solutions
- Cast/wrap the expression to string output or use a non-dictionary-encoded (value) selector path
- Set query context 'vectorize':'false' to force the non-vectorized engine
- Materialize the expression at ingest time as a real column and query that
- Upgrade Druid — newer versions support more expression vectorization cases
Example fix
// before expression: "a + b" used directly as dimension (multi-input, numeric) // after expression: "CONCAT(CAST(a AS STRING), '-', CAST(b AS STRING))" // single/multi handled via non-dict path, or disable vectorization
Defensive patterns
Strategy: validation
Validate before calling
// inspect the expression plan before choosing a dict-encoded selector
boolean supported = plan.is(ExpressionPlan.Trait.CONSTANT)
|| (plan.is(ExpressionPlan.Trait.SINGLE_INPUT_SCALAR)
&& plan.getOutputType() != null && plan.getOutputType().is(ExprType.STRING)); Type guard
boolean dictUsable = plan.getOutputType() != null && plan.getOutputType().is(ExprType.STRING);
Try / catch
try { sel = makeSingleValueDimensionVectorSelector(...); } catch (IllegalStateException e) { sel = makeVectorValueSelector(...); /* value path */ } Prevention
- Keep expression virtual columns used as dimensions single-input and string-output
- Materialize complex multi-input expressions as real columns at ingest
- Set 'vectorize':'false' when grouping on numeric expression columns
When it happens
Trigger: Vectorized query asks for a dictionary-encoded single-value dimension selector on an expression virtual column whose plan is not SINGLE_INPUT_SCALAR with STRING output (e.g. numeric expression, multi-column expression).
Common situations: Grouping on a numeric expression virtual column with vectorization on; expression virtual column combining two columns used as a dimension; older Druid versions with narrower expression vectorization support.
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
- Projected output type
- Aggregator[ ] cannot vectorize
- argument must be a LONG constant
- attempt to get boolean[] null vector from string[] only…
- attempt to get double[] from string[] only scalar binding
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/211c308c94f06630.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/virtual/ExpressionVectorSelectors.java:76
VectorColumnSelectorFactory factory,
Expr expression
)
{
final ExpressionPlan plan = ExpressionPlanner.plan(factory, expression);
Preconditions.checkArgument(plan.is(ExpressionPlan.Trait.VECTORIZABLE));
// only constant expressions are currently supported, nothing else should get here
if (plan.isConstant()) {
String constant = plan.getExpression().eval(InputBindings.nilBindings()).asString();
return ConstantVectorSelectors.singleValueDimensionVectorSelector(factory.getReadableVectorInspector(), constant);
}
if (plan.is(ExpressionPlan.Trait.SINGLE_INPUT_SCALAR) && (plan.getOutputType() != null && plan.getOutputType().is(ExprType.STRING))) {
return new SingleStringInputDeferredEvaluationExpressionDimensionVectorSelector(
factory.makeSingleValueDimensionSelector(DefaultDimensionSpec.of(plan.getSingleInputName())),
plan.getExpression()
);
}
throw new IllegalStateException("Only constant and single input string expressions currently support dictionary encoded selectors");
}
public static VectorValueSelector makeVectorValueSelector(
VectorColumnSelectorFactory factory,
Expr expression
)
{
final ExpressionPlan plan = ExpressionPlanner.plan(factory, expression);
Preconditions.checkArgument(plan.is(ExpressionPlan.Trait.VECTORIZABLE));
if (plan.isConstant()) {
return ConstantVectorSelectors.vectorValueSelector(
factory.getReadableVectorInspector(),
(Number) plan.getExpression().eval(InputBindings.nilBindings()).value()
);
}
final Expr.VectorInputBinding bindings = createVectorBindings(plan.getAnalysis(), factory);
final ExprVectorProcessor<?> processor = plan.getExpression().asVectorProcessor(bindings);View on GitHub (pinned to 9b90983fd2)