apache/beam · error · java.lang.RuntimeException
Unexpected join type
Error message
Unexpected join type ${realJoinType} What it means
Inside BeamSideInputJoinRel's sideInputJoin transform, after handling INNER, LEFT OUTER and RIGHT OUTER joins, a default branch throws this RuntimeException for any other join type. It is an internal invariant check: the planner should never route a join of this type to the side-input join implementation.
Solutions
- Rewrite the query to use INNER or LEFT/RIGHT OUTER JOIN (with the unbounded side on the outer side) instead of the unsupported join type.
- Check the Beam version and upgrade — if FULL OUTER reaches this path it is likely a planner bug; verify against the latest release.
- Inspect the plan (explain) to see why BeamSideInputJoinRel was chosen and adjust predicates/queries.
- If using custom join rules, fix them to exclude join types the side-input implementation cannot handle.
Example fix
-- before SELECT * FROM a FULL OUTER JOIN b ON a.k = b.k -- after SELECT * FROM a LEFT OUTER JOIN b ON a.k = b.k UNION ALL SELECT * FROM a RIGHT OUTER JOIN b ON a.k = b.k WHERE a.k IS NULL
Defensive patterns
Strategy: try-catch
Validate before calling
Set<JoinRelType> supported = EnumSet.of(JoinRelType.INNER, JoinRelType.LEFT, JoinRelType.RIGHT); if (!supported.contains(joinType)) { throw new IllegalArgumentException("Side-input join supports only INNER/LEFT/RIGHT"); } Type guard
boolean supportedJoinType = joinType == JoinRelType.INNER || joinType == JoinRelType.LEFT || joinType == JoinRelType.RIGHT;
Try / catch
try { result = pipeline.apply(SqlTransform.query(sql)); } catch (RuntimeException e) { if (e.getMessage().startsWith("Unexpected join type")) { /* rewrite query to supported join types */ } else { throw e; } } Prevention
- Restrict queries to INNER/LEFT/RIGHT OUTER joins for side-input paths
- Treat this as a planner bug signal — capture the query and file/inspect a Beam issue
- Run explain() on the query to confirm which join strategy is selected
- Pin and test a Beam version where planner behavior is known
When it happens
Trigger: The switch over realJoinType in BeamSideInputJoinRel.sideInputJoin reaches default — i.e. a join type other than INNER/LEFT/RIGHT OUTER reaches the side-input join path (e.g. FULL OUTER due to a planning bug or unsafe rewrite).
Common situations: Hitting it is usually a sign of a Calcite rule mismatch or a custom/vendored Beam version where a new join type got planned to BeamSideInputJoinRel; rarely user-triggered directly.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Attempting to create a table with unexpected Calcite Schema…
- Attempting to drop a catalog
- Attempting to drop a table using unexpected Calcite Schema…
- Attempting to drop database
- Cannot get column index from
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/acfc7516c89f6547.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamSideInputJoinRel.java:191
PCollection<Row> joined;
switch (realJoinType) {
case INNER:
joined =
realLeftRows.apply(
org.apache.beam.sdk.schemas.transforms.Join.<Row, Row>innerBroadcastJoin(
realRightRows)
.on(FieldsEqual.left(realLeftKeyFields).right(realRightKeyFields)));
break;
case LEFT:
joined =
realLeftRows.apply(
org.apache.beam.sdk.schemas.transforms.Join.<Row, Row>leftOuterBroadcastJoin(
realRightRows)
.on(FieldsEqual.left(realLeftKeyFields).right(realRightKeyFields)));
break;
default:
throw new RuntimeException("Unexpected join type " + realJoinType);
}
Schema schema = CalciteUtils.toSchema(getRowType());
String lhsSelect = org.apache.beam.sdk.schemas.transforms.Join.LHS_TAG + ".*";
String rhsSelect = org.apache.beam.sdk.schemas.transforms.Join.RHS_TAG + ".*";
PCollection<Row> selected =
!swapped
? joined.apply(Select.<Row>fieldNames(lhsSelect, rhsSelect).withOutputSchema(schema))
: joined.apply(Select.<Row>fieldNames(rhsSelect, lhsSelect).withOutputSchema(schema));
return selected;
}
}
View on GitHub (pinned to 12126d8942)