apache/beam · error · java.lang.UnsupportedOperationException
Only support column reference or struct field access in conj
Error message
Only support column reference or struct field access in conjunction clause
What it means
After confirming an '=' conjunct, extractJoinPairOfRexNodes checks that both operands are legal join keys: plain column references (RexInputRef) or struct field accesses. Anything else (literals, function calls, casts) in the join clause is rejected with UnsupportedOperationException.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamJoinRel.java:195
pairs.add(pair);
}
} else if ("=".equals(call.getOperator().getName())) {
pairs.add(extractJoinPairOfRexNodes(call));
} else {
throw new UnsupportedOperationException(
"Operator " + call.getOperator().getName() + " is not supported in join condition");
}
return pairs;
}
private static Pair<RexNode, RexNode> extractJoinPairOfRexNodes(RexCall rexCall) {
if (!rexCall.getOperator().getName().equals("=")) {
throw new UnsupportedOperationException("Non equi-join is not supported");
}
if (isIllegalJoinConjunctionClause(rexCall)) {
throw new UnsupportedOperationException(
"Only support column reference or struct field access in conjunction clause");
}
int leftIndex = getColumnIndex(rexCall.getOperands().get(0));
int rightIndex = getColumnIndex(rexCall.getOperands().get(1));
if (leftIndex < rightIndex) {
return new Pair<>(rexCall.getOperands().get(0), rexCall.getOperands().get(1));
} else {
return new Pair<>(rexCall.getOperands().get(1), rexCall.getOperands().get(0));
}
}
// Only support {RexInputRef | RexFieldAccess} = {RexInputRef | RexFieldAccess}
private static boolean isIllegalJoinConjunctionClause(RexCall rexCall) {
return (!(rexCall.getOperands().get(0) instanceof RexInputRef)
&& !(rexCall.getOperands().get(0) instanceof RexFieldAccess))
|| (!(rexCall.getOperands().get(1) instanceof RexInputRef)
&& !(rexCall.getOperands().get(1) instanceof RexFieldAccess));View on GitHub (pinned to 12126d8942)
Solutions
- Join on raw columns only; apply functions/casts in a subquery or CTE before the join (e.g. project UPPER(name) AS name_norm then join on name_norm)
- Remove literals from the join clause and express them as WHERE filters
- Cast one of the source tables (via a subquery) so both key columns share the same type without in-condition casts
Example fix
// before SELECT * FROM a JOIN b ON UPPER(a.name) = b.name; // after SELECT * FROM (SELECT UPPER(name) AS name_norm, * FROM a) a JOIN b ON a.name_norm = b.name;
Defensive patterns
Strategy: validation
Validate before calling
// Every join operand must be a column ref or struct field access
for (RexNode operand : joinKeyOperands) {
if (!(operand instanceof RexInputRef || operand instanceof RexFieldAccess)) {
throw new IllegalArgumentException("Join keys must be plain columns or struct fields");
}
} Try / catch
try {
result = sqlEnv.sqlQuery(q).evaluate();
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("Only support column reference or struct field access")) {
q = precomputeJoinKeysInSubquery(q);
} else throw e;
} Prevention
- Never put functions, casts, or literals in join ON clauses
- Normalize keys in subqueries/CTEs before joining
- Keep both join-key columns the same type at the source
When it happens
Trigger: Join conditions containing expressions rather than bare columns, e.g. ON UPPER(a.name) = b.name or ON a.id = CAST(b.id AS BIGINT) or a constant on one side.
Common situations: Joining on computed/normalized values; comparing a join key to a literal; applying type casts inside the join condition.
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
- CROSS JOIN, JOIN ON FALSE is not supported!
- Operator ${operatorName} is not supported in join condition
- Non equi-join is not supported
- Cannot get column index from ${type}
- FULL OUTER JOIN is not supported when join a bounded table w
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/750a5ab09e83463f.
Report an issue: GitHub.