{"record":{"id":"64247039e6708c20","repo":"apache/druid","slug":"expected-expression-with-just-one-binding-642470","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/SingleStringInputCachingExpressionColumnValueSelector.java","lineNumber":64,"sourceCode":"  private final DimensionSelector selector;\n  private final Expr expression;\n  private final Expr.ObjectBinding bindings;\n  @Nullable\n  private final ExprEval[] arrayEvalCache;\n  @Nullable\n  private final LruEvalCache lruEvalCache;\n\n  public SingleStringInputCachingExpressionColumnValueSelector(\n      final DimensionSelector selector,\n      final Expr expression,\n      @Nullable final 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\n    final Supplier<Object> inputSupplier = ExpressionSelectors.supplierFromDimensionSelector(selector, false, false);\n    this.bindings = InputBindings.forInputSupplier(ExpressionType.STRING, inputSupplier);\n\n    if (selector.getValueCardinality() == DimensionDictionarySelector.CARDINALITY_UNKNOWN) {\n      throw new ISE(\"Selector must have a dictionary\");\n    } else if (selector.getValueCardinality() <= CACHE_SIZE) {\n      arrayEvalCache = new ExprEval[selector.getValueCardinality()];\n      lruEvalCache = null;\n    } else {\n      arrayEvalCache = null;\n      lruEvalCache = new LruEvalCache(expression, bindings);\n    }\n  }","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/virtual/SingleStringInputCachingExpressionColumnValueSelector.java#L46-L82","documentation":"Identical single-binding constraint as the long-input variant: SingleStringInputCachingExpressionColumnValueSelector caches string expression evaluations per dictionary value, which is only valid when the expression depends on exactly one binding. Any other binding count causes an ISE in the constructor.","triggerScenarios":"Constructor invoked with an Expr whose required bindings size is not exactly 1, e.g. expression over two dimensions or a constant.","commonSituations":"Manually composing expression selectors in custom code, or engine routing bugs where a multi-column expression is handed to a single-input selector factory.","solutions":["Pass an expression with exactly one string dimension binding","Fall back to ExpressionSelectors.supplierFromDimensionSelector / general expression selector for other shapes","Assert bindings count in your factory before choosing this selector"],"exampleFix":"// before\nnew SingleStringInputCachingExpressionColumnValueSelector(sel, expr(concat(a, b)))\n// after\nnew SingleStringInputCachingExpressionColumnValueSelector(sel, expr(upper(a))) // single binding","handlingStrategy":"validation","validationCode":"if (expr.analyzeInputs().getRequiredBindings().size() != 1) {\n  // route to general expression selector instead\n}","typeGuard":"boolean isSingleStringBinding(Expr e) {\n  return e.analyzeInputs().getRequiredBindings().size() == 1;\n}","tryCatchPattern":"try {\n  return new SingleStringInputCachingExpressionColumnValueSelector(sel, expr, useLru, rowIdSupplier);\n} catch (ISE e) {\n  return generalExpressionSelector(sel, expr, rowIdSupplier);\n}","preventionTips":["Verify binding count before constructing single-input selectors","Use ExpressionSelectors factory methods rather than instantiating selectors directly","Keep expressions on single virtual columns when intending cached evaluation"],"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"}