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

  1. Ensure the expression reads exactly one long input column binding
  2. Use the general (non-single-input) ExpressionColumnValueSelector for multi-binding or constant expressions
  3. 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

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


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)