apache/beam · error · java.lang.UnsupportedOperationException
Side input join can only be used if one table is bounded.
Error message
Side input join can only be used if one table is bounded.
What it means
The side-input join implementation requires exactly one side of the join to be bounded: the bounded side is materialized as a side input while the other side streams. If both inputs are unbounded (both streaming), side-input join cannot be used and Beam SQL throws this UnsupportedOperationException during translation.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamSideInputJoinRel.java:118
// the unbounded & RIGHT OUTER JOIN where right side of the join must be the unbounded
if (joinType == JoinRelType.FULL) {
throw new UnsupportedOperationException(
"FULL OUTER JOIN is not supported when join "
+ "a bounded table with an unbounded table.");
}
BeamRelNode leftRelNode = BeamSqlRelUtils.getBeamRelInput(left);
BeamRelNode rightRelNode = BeamSqlRelUtils.getBeamRelInput(right);
if ((joinType == JoinRelType.LEFT && leftRelNode.isBounded() == PCollection.IsBounded.BOUNDED)
|| (joinType == JoinRelType.RIGHT
&& rightRelNode.isBounded() == PCollection.IsBounded.BOUNDED)) {
throw new UnsupportedOperationException(
String.format("%s side of an OUTER JOIN must be Unbounded table.", joinType.name()));
}
if (leftRelNode.isBounded() == IsBounded.UNBOUNDED
&& rightRelNode.isBounded() == IsBounded.UNBOUNDED) {
throw new UnsupportedOperationException(
"Side input join can only be used if one table is bounded.");
}
return new SideInputJoin();
}
private class SideInputJoin extends PTransform<PCollectionList<Row>, PCollection<Row>> {
@Override
public PCollection<Row> expand(PCollectionList<Row> pinput) {
Schema leftSchema = pinput.get(0).getSchema();
Schema rightSchema = pinput.get(1).getSchema();
PCollection<Row> leftRows =
pinput
.get(0)
.apply(
"left_TimestampCombiner",
Window.<Row>configure().withTimestampCombiner(TimestampCombiner.EARLIEST));
PCollection<Row> rightRows =View on GitHub (pinned to 12126d8942)
Solutions
- Make one side bounded (e.g. read a static reference table from a file/DB) so the side-input join precondition holds.
- Use a true streaming join construct instead: window both PCollections and use CoGroupByKey, or rewrite the query so Calcite selects a streaming-capable join strategy.
- Window both sides identically and join within windows if the sources are both unbounded.
- Check the physical plan and add hints/constraints so the join rule does not pick BeamSideInputJoinRel for two unbounded inputs.
Example fix
-- before SELECT * FROM stream1 JOIN stream2 ON stream1.k = stream2.k -- after SELECT * FROM stream1 JOIN bounded_lookup_table ON stream1.k = bounded_lookup_table.k
Defensive patterns
Strategy: validation
Validate before calling
if (left.isBounded() == IsBounded.UNBOUNDED && right.isBounded() == IsBounded.UNBOUNDED) { throw new IllegalArgumentException("Side-input join requires one bounded table; use CoGroupByKey/windowed join for stream-stream"); } Type guard
boolean oneBounded = left.isBounded() != right.isBounded();
Try / catch
try { pipeline.apply(SqlTransform.query(sql)); } catch (UnsupportedOperationException e) { if (e.getMessage().contains("one table is bounded")) { /* switch to windowed CoGroup join */ } else { throw e; } } Prevention
- Never join two unbounded sources with a query planned as side-input join
- Back one side of lookup-style joins with a bounded reference table
- Use CoGroupByKey with matching windows for stream-stream joins
- Verify boundedness of both inputs during pipeline assembly
When it happens
Trigger: BeamSideInputJoinRel.buildPTransform detects leftRelNode.isBounded()==UNBOUNDED && rightRelNode.isBounded()==UNBOUNDED, i.e. a streaming-streaming join planned as a side-input join.
Common situations: Joining two streaming sources (e.g. two Pub/Sub topics) in Beam SQL and expecting the side-input optimization to apply; users often think side-input join is the general streaming join, but it is only for one-batched-side joins.
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
- FULL OUTER JOIN is not supported when join a bounded table w
- %s side of an OUTER JOIN must be Unbounded table.
- FULL OUTER JOIN is not supported when join a Seekable table
- %s side of an OUTER JOIN must be a non Seekable table.
- Please explicitly specify windowing in SQL query using HOP/T
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bf2cbed34e13fb1f.
Report an issue: GitHub.