{"record":{"id":"c2aa27861b6145c7","repo":"apache/druid","slug":"expected-expression-with-just-one-binding","errorCode":null,"errorMessage":"Expected expression with just one binding","messagePattern":"Expected expression with just one binding","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java","lineNumber":73,"sourceCode":"  @Nullable\n  private ExprEval lastOutput;\n\n  // Computed output value for null.\n  @MonotonicNonNull\n  private ExprEval nullOutput;\n\n  public SingleLongInputCachingExpressionColumnValueSelector(\n      final ColumnValueSelector selector,\n      final Expr expression,\n      final boolean useLruCache,\n      @Nullable RowIdSupplier rowIdSupplier\n  )\n  {\n    super(rowIdSupplier);\n\n    // Verify expression has just one binding.\n    if (expression.analyzeInputs().getRequiredBindings().size() != 1) {\n      throw new ISE(\"Expected expression with just one binding\");\n    }\n\n    this.selector = Preconditions.checkNotNull(selector, \"selector\");\n    this.expression = Preconditions.checkNotNull(expression, \"expression\");\n    this.lruEvalCache = useLruCache ? new LruEvalCache() : null;\n  }\n\n  @Override\n  public void inspectRuntimeShape(final RuntimeShapeInspector inspector)\n  {\n    super.inspectRuntimeShape(inspector);\n    inspector.visit(\"selector\", selector);\n    inspector.visit(\"expression\", expression);\n  }\n\n  @Nonnull\n  @Override\n  protected ExprEval<?> eval()","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/virtual/SingleLongInputCachingExpressionColumnValueSelector.java#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nnew SingleLongInputCachingExpressionColumnValueSelector(base, col1 + col2 expression, ...) // 2 bindings\n// after\nExpressionSelectors.makeExprColumnValueSelector(...) // general selector for multi-binding expressions","handlingStrategy":"validation","validationCode":"if (expr.analyzeInputs().getRequiredBindings().size() != 1) {\n  throw new IllegalStateException(\"single-input selector requires exactly one binding\");\n}","typeGuard":"boolean isSingleBinding(Expr e) {\n  return e.analyzeInputs().getRequiredBindings().size() == 1;\n}","tryCatchPattern":"try {\n  return new SingleLongInputCachingExpressionColumnValueSelector(...);\n} catch (ISE e) {\n  return ExpressionSelectors.makeExprColumnValueSelector(colSelectorFactory, expr, ...); // general selector\n}","preventionTips":["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"],"tags":["druid","expression","selector","internal-invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}