apache/druid · error · IllegalArgumentException

Cannot join lookup with non-equi condition: %s

Error message

Cannot join lookup with non-equi condition: %s

What it means

Lookup joins only support equi-joins on the lookup's single key column. LookupJoinMatcher.create rejects a JoinCondition that contains any non-equi (inequality) condition, because a hash-based lookup cannot evaluate arbitrary predicates.

Source

Thrown at processing/src/main/java/org/apache/druid/segment/join/lookup/LookupJoinMatcher.java:194

      );
    }
  }

  public static LookupJoinMatcher create(
      LookupExtractor extractor,
      ColumnSelectorFactory leftSelectorFactory,
      JoinConditionAnalysis condition,
      boolean remainderNeeded
  )
  {
    final List<Expr> keyExprs;

    if (condition.isAlwaysTrue()) {
      keyExprs = null;
    } else if (condition.isAlwaysFalse()) {
      keyExprs = null;
    } else if (!condition.getNonEquiConditions().isEmpty()) {
      throw new IAE("Cannot join lookup with non-equi condition: %s", condition);
    } else if (!condition.getRightEquiConditionKeys()
                         .stream()
                         .allMatch(LookupColumnSelectorFactory.KEY_COLUMN::equals)) {
      throw new IAE("Cannot join lookup with condition referring to non-key column: %s", condition);
    } else {
      keyExprs = condition.getEquiConditions().stream().map(Equality::getLeftExpr).collect(Collectors.toList());
    }

    return new LookupJoinMatcher(extractor, leftSelectorFactory, condition, keyExprs, remainderNeeded);
  }

  @Override
  public ColumnSelectorFactory getColumnSelectorFactory()
  {
    return selectorFactory;
  }

  @Override

View on GitHub (pinned to 9b90983fd2)

Solutions

  1. Move the non-equi condition into the WHERE clause (applied after the join) instead of the ON clause
  2. Restrict the lookup join ON clause to pure equality on the lookup key column
  3. Use a regular table join instead of a lookup if range predicates in ON are required

Example fix

// before
SELECT ... FROM t JOIN lookup l ON t.k = l.k AND t.ts >= l.start
// after
SELECT ... FROM t JOIN lookup l ON t.k = l.k WHERE t.ts >= l.start
Defensive patterns

Strategy: validation

Validate before calling

if (!condition.getNonEquiConditions().isEmpty())
  throw new IllegalArgumentException("move non-equi conditions to WHERE for lookup joins: " + condition);

Try / catch

try { LookupJoinMatcher.create(...); } catch (IAE e) { if (e.getMessage().startsWith("Cannot join lookup with non-equi")) { /* rewrite query or surface to user */ } }

Prevention

When it happens

Trigger: Creating a LookupJoinMatcher with a join condition containing non-equi clauses, e.g. ON l.k = t.k AND t.ts > l.start, when joining a lookup table.

Common situations: SQL with an ON clause mixing equality and range predicates against a lookup; hand-written native join clauses with extra inequality conditions on a lookup datasource.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07). Data as JSON: /api/errors/38f4105d70a7182a. Report an issue: GitHub.