apache/beam · error · java.lang.UnsupportedOperationException

CROSS JOIN, JOIN ON FALSE is not supported!

Error message

CROSS JOIN, JOIN ON FALSE is not supported!

What it means

BeamJoinRel validates join conditions by extracting equi-join predicate pairs from the Calcite RexNode tree. A RexLiteral condition means the join has no column-pair predicate at all (CROSS JOIN, or JOIN ON TRUE/FALSE), which Beam SQL does not support, so it throws UnsupportedOperationException.

Source

Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamJoinRel.java:168

   * This method checks if a join is legal and can be converted into Beam SQL. It is used during
   * planning and applying {@link
   * org.apache.beam.sdk.extensions.sql.impl.rule.BeamJoinAssociateRule} and {@link
   * org.apache.beam.sdk.extensions.sql.impl.rule.BeamJoinPushThroughJoinRule}
   */
  public static boolean isJoinLegal(Join join) {
    try {
      extractJoinRexNodes(join.getCondition());
    } catch (UnsupportedOperationException e) {
      return false;
    }
    return true;
  }

  static List<Pair<RexNode, RexNode>> extractJoinRexNodes(RexNode condition) {
    // it's a CROSS JOIN because: condition == true
    // or it's a JOIN ON false because: condition == false
    if (condition instanceof RexLiteral) {
      throw new UnsupportedOperationException("CROSS JOIN, JOIN ON FALSE is not supported!");
    }

    RexCall call = (RexCall) condition;
    List<Pair<RexNode, RexNode>> pairs = new ArrayList<>();
    if ("AND".equals(call.getOperator().getName())) {
      List<RexNode> operands = call.getOperands();
      for (RexNode rexNode : operands) {
        Pair<RexNode, RexNode> pair = extractJoinPairOfRexNodes((RexCall) rexNode);
        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;

View on GitHub (pinned to 12126d8942)

Solutions

  1. Rewrite the query to include an equality join predicate, e.g. JOIN ... ON a.id = b.id
  2. If a cartesian product is intended, add an explicit true equality filter inside a WHERE on unique keys or emulate with a cross product via UDFs (e.g. generate pairs then filter)
  3. Handle the UnsupportedOperationException at the API layer and reject/rewrite the query before submission

Example fix

// before
SELECT * FROM orders CROSS JOIN customers;
// after
SELECT * FROM orders JOIN customers ON orders.customer_id = customers.id;
Defensive patterns

Strategy: validation

Validate before calling

// Reject constant join conditions client-side
if (joinCondition == null || isConstantBooleanLiteral(joinCondition)) {
  throw new IllegalArgumentException("CROSS JOIN / JOIN ON literal is not supported; provide an equi-join predicate");
}

Try / catch

try {
  beamSqlEnv.sqlQuery(q).evaluate();
} catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("CROSS JOIN, JOIN ON FALSE")) {
    q = rewriteToEquiJoinOrFilteredCrossProduct(q); // substitute an ON a.x = b.x predicate
  } else throw e;
}

Prevention

When it happens

Trigger: Executing SQL like SELECT * FROM a CROSS JOIN b, or an explicit JOIN with a constant condition (ON TRUE / ON FALSE), so extractJoinRexNodes receives a RexLiteral instead of a RexCall.

Common situations: Porting queries written for databases that allow cross joins; accidentally omitting the ON clause; programmatic RelNode construction with a literal 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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/3535aa2300403c0b. Report an issue: GitHub.