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

  1. 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.
  2. Check the Beam version and upgrade — if FULL OUTER reaches this path it is likely a planner bug; verify against the latest release.
  3. Inspect the plan (explain) to see why BeamSideInputJoinRel was chosen and adjust predicates/queries.
  4. 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

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


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)