apache/druid · error · IllegalArgumentException
Cannot handle non-equijoin condition: %s
Error message
Cannot handle non-equijoin condition: %s
What it means
The MSQ sort-merge join stage only supports pure equi-joins where the left side of each equality is a simple column identifier. validateCondition throws this IllegalArgumentException when the join condition contains any non-equi predicate (e.g. t1.a > t2.b, LIKE, OR of inequalities), which the shuffle-based merge join implementation cannot evaluate.
Source
Thrown at multi-stage-query/src/main/java/org/apache/druid/msq/querykit/common/SortMergeJoinStageProcessor.java:271
return retVal.toArray(new int[0]);
}
/**
* Validates that a join condition can be handled by this processor. Returns the condition if it can be handled.
* Throws {@link IllegalArgumentException} if the condition cannot be handled.
*/
public static JoinConditionAnalysis validateCondition(final JoinConditionAnalysis condition)
{
if (condition.isAlwaysTrue()) {
return condition;
}
if (condition.isAlwaysFalse()) {
throw new IAE("Cannot handle constant condition: %s", condition.getOriginalExpression());
}
if (condition.getNonEquiConditions().size() > 0) {
throw new IAE("Cannot handle non-equijoin condition: %s", condition.getOriginalExpression());
}
if (condition.getEquiConditions().stream().anyMatch(c -> !c.getLeftExpr().isIdentifier())) {
throw new IAE(
"Cannot handle equality condition involving left-hand expression: %s",
condition.getOriginalExpression()
);
}
return condition;
}
/**
* Validates that all signatures from {@link #collectAndReadPartitions(ExecutionContext)} are prefixed by the
* provided {@code keyColumns}.
*/
private static Int2ObjectMap<List<ReadableInput>> validateInputFrameSignatures(
final Int2ObjectMap<List<ReadableInput>> inputsByPartition,View on GitHub (pinned to 9b90983fd2)
Solutions
- Move the non-equi predicate out of the JOIN ON clause into a WHERE clause applied after the join.
- Rewrite the condition as a pure equality join and filter rows afterwards in a separate WHERE or HAVING stage.
- Use a different join strategy that supports non-equi conditions (e.g. broadcast/join via the native engine instead of MSQ sort-merge join).
- Ensure equi-join left expressions are plain column identifiers, not expressions (see related error).
Example fix
// before SELECT ... FROM t1 JOIN t2 ON t1.id = t2.id AND t1.ts > t2.ts // after SELECT ... FROM t1 JOIN t2 ON t1.id = t2.id WHERE t1.ts > t2.ts
Defensive patterns
Strategy: validation
Validate before calling
// Client-side check before submitting an MSQ join
function validateJoinCondition(onClause) {
const hasNonEqui = onClause.predicates.some(p => !p.isEquality);
if (hasNonEqui) throw new Error('MSQ sort-merge join requires pure equi-join ON conditions');
const nonIdentifierLeft = onClause.predicates.some(p => p.isEquality && !isColumnRef(p.left));
if (nonIdentifierLeft) throw new Error('MSQ equi-join left side must be a plain column');
} Type guard
function isPlainColumnRef(expr) { return expr.type === 'identifier' || expr.type === 'column'; } Prevention
- Keep join ON clauses limited to simple column equality.
- Filter non-join predicates in WHERE, not ON.
- Avoid functions or arithmetic on join keys in MSQ queries.
- Test migrated SQL against MSQ limitations before production use.
When it happens
Trigger: Running a query via the MSQ/dsql engine whose JOIN ... ON clause includes an inequality, range, LIKE, IS NULL, or other non-equality predicate, or mixes equi and non-equi conditions (e.g. ON a.id = b.id AND a.ts > b.ts).
Common situations: Porting SQL written for traditional databases (Postgres/MySQL) that freely uses non-equijoin conditions to Druid MSQ; adding time-range or fuzzy-match predicates to a join ON clause; hand-written native join queries with mixed conditions.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- Cannot handle constant condition: %s
- Cannot handle equality condition involving left-hand express
- Unknown
- BroadcastTablesTooLarge
- FrameTooLarge
AI-assisted analysis of apache/druid@9b90983fd2 (2026-09-07).
Data as JSON: /api/errors/047deb3541793c3e.
Report an issue: GitHub.