{"record":{"id":"ca2c28edc6776820","repo":"apache/druid","slug":"selector-of-class-s-does-not-have-a-dictionary","errorCode":null,"errorMessage":"Selector of class[%s] does not have a dictionary, cannot use it.","messagePattern":"Selector of class\\[(.+?)\\] does not have a dictionary, cannot use it\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/virtual/SingleStringInputDeferredEvaluationExpressionDimensionSelector.java","lineNumber":62,"sourceCode":" *\n * @see SingleStringInputDeferredEvaluationExpressionDimensionVectorSelector for the vectorized version of\n * this selector.\n */\npublic class SingleStringInputDeferredEvaluationExpressionDimensionSelector implements DimensionSelector\n{\n  private final DimensionSelector selector;\n  private final Expr expression;\n  private final SingleInputBindings bindings = new SingleInputBindings(ExpressionType.STRING);\n\n  public SingleStringInputDeferredEvaluationExpressionDimensionSelector(\n      final DimensionSelector selector,\n      final Expr expression\n  )\n  {\n    // Verify selector has a working dictionary.\n    if (selector.getValueCardinality() == DimensionDictionarySelector.CARDINALITY_UNKNOWN\n        || !selector.nameLookupPossibleInAdvance()) {\n      throw new ISE(\"Selector of class[%s] does not have a dictionary, cannot use it.\", selector.getClass().getName());\n    }\n\n    this.selector = Preconditions.checkNotNull(selector, \"selector\");\n    this.expression = Preconditions.checkNotNull(expression, \"expression\");\n  }\n\n  @Override\n  public void inspectRuntimeShape(final RuntimeShapeInspector inspector)\n  {\n    inspector.visit(\"selector\", selector);\n    inspector.visit(\"expression\", expression);\n  }\n\n  /**\n   * Get the underlying selector {@link IndexedInts} row\n   */\n  @Override\n  public IndexedInts getRow()","sourceCodeStart":44,"sourceCodeEnd":80,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/virtual/SingleStringInputDeferredEvaluationExpressionDimensionSelector.java#L44-L80","documentation":"SingleStringInputDeferredEvaluationExpressionDimensionSelector requires the wrapped dimension selector to expose a usable dictionary: known value cardinality and name lookup possible in advance. Selectors without a dictionary (CARDINALITY_UNKNOWN or nameLookupPossibleInAdvance()==false) cannot back deferred expression evaluation, so an ISE naming the offending class is thrown.","triggerScenarios":"Constructor called with a selector where getValueCardinality() == CARDINALITY_UNKNOWN or nameLookupPossibleInAdvance() is false — e.g. non-dictionary-encoded strings, virtual/unknown-cardinality selectors.","commonSituations":"Applying expression virtual columns on top of non-dimension (row-based) selectors, query planning mixing grouped results with expression selectors, or custom DimensionSelector implementations lacking dictionaries.","solutions":["Provide a dictionary-encoded dimension selector for the input column","Re-encode the column with dictionary encoding at ingestion","Use a selector path that does not require dictionary lookup (e.g. value-selector based expression evaluation)","Call getValueCardinality() and nameLookupPossibleInAdvance() before construction to guard"],"exampleFix":"// before\nnew SingleStringInputDeferredEvaluationExpressionDimensionSelector(nonDictSelector, expr)\n// after\nPreconditions.checkArgument(sel.nameLookupPossibleInAdvance(), \"need dictionary selector\");\nnew SingleStringInputDeferredEvaluationExpressionDimensionSelector(dictSelector, expr);","handlingStrategy":"type-guard","validationCode":"boolean usable = sel.getValueCardinality() != CARDINALITY_UNKNOWN && sel.nameLookupPossibleInAdvance();","typeGuard":"boolean isDictionarySelector(DimensionDictionarySelector sel) {\n  return sel.getValueCardinality() != CARDINALITY_UNKNOWN && sel.nameLookupPossibleInAdvance();\n}","tryCatchPattern":"try {\n  return new SingleStringInputDeferredEvaluationExpressionDimensionSelector(sel, expr);\n} catch (ISE e) {\n  // fall back to a value-selector based expression evaluation path\n  return fallbackExpressionProcessor(expr, sel);\n}","preventionTips":["Confirm nameLookupPossibleInAdvance() before wrapping selectors","Use dictionary-encoded string columns for expression virtual columns","Add guards in custom selector factories for unknown-cardinality inputs"],"tags":["druid","expression","dictionary-encoding"],"backgroundTag":"invalid-argument-value","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}