{"record":{"id":"d729cc3a0cda771c","repo":"apache/druid","slug":"cannot-join-lookup-with-condition-referring-to-non","errorCode":null,"errorMessage":"Cannot join lookup with condition referring to non-key column: %s","messagePattern":"Cannot join lookup with condition referring to non-key column: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/segment/join/lookup/LookupJoinMatcher.java","lineNumber":198,"sourceCode":"  public static LookupJoinMatcher create(\n      LookupExtractor extractor,\n      ColumnSelectorFactory leftSelectorFactory,\n      JoinConditionAnalysis condition,\n      boolean remainderNeeded\n  )\n  {\n    final List<Expr> keyExprs;\n\n    if (condition.isAlwaysTrue()) {\n      keyExprs = null;\n    } else if (condition.isAlwaysFalse()) {\n      keyExprs = null;\n    } else if (!condition.getNonEquiConditions().isEmpty()) {\n      throw new IAE(\"Cannot join lookup with non-equi condition: %s\", condition);\n    } else if (!condition.getRightEquiConditionKeys()\n                         .stream()\n                         .allMatch(LookupColumnSelectorFactory.KEY_COLUMN::equals)) {\n      throw new IAE(\"Cannot join lookup with condition referring to non-key column: %s\", condition);\n    } else {\n      keyExprs = condition.getEquiConditions().stream().map(Equality::getLeftExpr).collect(Collectors.toList());\n    }\n\n    return new LookupJoinMatcher(extractor, leftSelectorFactory, condition, keyExprs, remainderNeeded);\n  }\n\n  @Override\n  public ColumnSelectorFactory getColumnSelectorFactory()\n  {\n    return selectorFactory;\n  }\n\n  @Override\n  public void matchCondition()\n  {\n    currentIterator = null;\n    matchingRemainder = false;","sourceCodeStart":180,"sourceCodeEnd":216,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/segment/join/lookup/LookupJoinMatcher.java#L180-L216","documentation":"Lookup joins require all equi-conditions on the right side to reference the lookup's designated key column (LookupColumnSelectorFactory.KEY_COLUMN). If a condition refers to any other lookup column, LookupJoinMatcher.create throws this IllegalArgumentException since only the key can be matched.","triggerScenarios":"Creating a LookupJoinMatcher with an equi condition whose right-hand key is not the lookup key column, e.g. ON t.k = l.some_other_column.","commonSituations":"SQL joining a lookup on a non-key column of the lookup; generated native join clauses referencing lookup value columns instead of __key; lookup registered with unexpected key naming after refactoring.","solutions":["Rewrite the join so it equates on the lookup's key column only","Create a new lookup keyed by the column you actually want to join on","If using SQL, join against the lookup's key (usually exposed as the lookup key) rather than a value column"],"exampleFix":"// before\nJOIN lookup l ON t.k = l.value_col\n// after\nJOIN lookup l ON t.k = l.__key -- or create a lookup keyed by value_col","handlingStrategy":"validation","validationCode":"boolean ok = condition.getRightEquiConditionKeys().stream()\n  .allMatch(LookupColumnSelectorFactory.KEY_COLUMN::equals);\nif (!ok) throw new IllegalArgumentException(\"lookup join must reference key column\");","typeGuard":null,"tryCatchPattern":"try { LookupJoinMatcher.create(...); } catch (IAE e) { /* rewrite to key column or create appropriately keyed lookup */ }","preventionTips":["Join only on the lookup's key column (__key)","Create dedicated lookups when joining on different columns","Check right-hand condition keys during query generation"],"tags":["java","join","lookup","sql","druid"],"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"}