apache/druid · error · IllegalStateException
Expected expression with just one binding
Error message
Expected expression with just one binding
What it means
SingleLongInputCachingExpressionColumnValueSelector is an optimization that caches expression results keyed by the single input long column. It requires the expression to reference exactly one required binding; if the expression has zero or multiple required bindings the cache cannot be keyed correctly, so the constructor throws ISE.
Solutions
- Ensure the expression reads exactly one long input column binding
- Use the general (non-single-input) ExpressionColumnValueSelector for multi-binding or constant expressions
- Check the expression via expression.analyzeInputs().getRequiredBindings() before construction
Example fix
// before new SingleLongInputCachingExpressionColumnValueSelector(base, col1 + col2 expression, ...) // 2 bindings // after ExpressionSelectors.makeExprColumnValueSelector(...) // general selector for multi-binding expressions
Defensive patterns
Strategy: validation
Validate before calling
if (expr.analyzeInputs().getRequiredBindings().size() != 1) {
throw new IllegalStateException("single-input selector requires exactly one binding");
} Type guard
boolean isSingleBinding(Expr e) {
return e.analyzeInputs().getRequiredBindings().size() == 1;
} Try / catch
try {
return new SingleLongInputCachingExpressionColumnValueSelector(...);
} catch (ISE e) {
return ExpressionSelectors.makeExprColumnValueSelector(colSelectorFactory, expr, ...); // general selector
} Prevention
- Check analyzeInputs().getRequiredBindings() before choosing a single-input selector
- Route multi-column expressions to general expression selectors
- Prefer Druid's ExpressionSelectors factories over direct selector construction
When it happens
Trigger: Constructing the selector with an Expr whose analyzeInputs().getRequiredBindings() returns a size != 1 — e.g. an expression referencing two columns, or a constant expression with no column binding.
Common situations: Custom virtual columns or expression planners wiring a multi-column or constant expression into the single-input caching selector; internal factory usually picks the right selector, so this surfaces when building selectors manually or after engine changes.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Expected expression with just one binding
- attempt to get boolean[] null vector from string[] only…
- attempt to get double[] from string[] only scalar binding
- attempt to get long[] from string[] only scalar binding
- Can only handle [ ], got [ ]
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/c2aa27861b6145c7.
Report an issue: GitHub.
Appendix: source
Thrown at processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java:73
@Nullable
private ExprEval lastOutput;
// Computed output value for null.
@MonotonicNonNull
private ExprEval nullOutput;
public SingleLongInputCachingExpressionColumnValueSelector(
final ColumnValueSelector selector,
final Expr expression,
final boolean useLruCache,
@Nullable RowIdSupplier rowIdSupplier
)
{
super(rowIdSupplier);
// Verify expression has just one binding.
if (expression.analyzeInputs().getRequiredBindings().size() != 1) {
throw new ISE("Expected expression with just one binding");
}
this.selector = Preconditions.checkNotNull(selector, "selector");
this.expression = Preconditions.checkNotNull(expression, "expression");
this.lruEvalCache = useLruCache ? new LruEvalCache() : null;
}
@Override
public void inspectRuntimeShape(final RuntimeShapeInspector inspector)
{
super.inspectRuntimeShape(inspector);
inspector.visit("selector", selector);
inspector.visit("expression", expression);
}
@Nonnull
@Override
protected ExprEval<?> eval()View on GitHub (pinned to 9b90983fd2)