apache/beam · error · java.lang.IllegalArgumentException
Cannot get limit count from RelNode tree with root
Error message
Cannot get limit count from RelNode tree with root ${relTypeName} What it means
During SQL LIMIT planning, BeamEnumerableConverter walks the RelNode tree to extract the row-count limit. It recognizes only BeamSortRel (direct LIMIT) and AbstractBeamCalcRel (LIMIT under a calc); any other root shape makes planning fail with this IllegalArgumentException.
Solutions
- Rewrite the query so LIMIT appears in a shape the converter supports (a plain sort/limit or a calc directly over it)
- Check the Beam version; newer releases extend getLimitCount to more RelNode types, so upgrade
- If extending Beam, add a branch in getLimitCount for your RelNode type exposing its count
Example fix
// before
throw new IllegalArgumentException("Cannot get limit count from RelNode tree with root " + node.getRelTypeName());
// after
if (node instanceof BeamSetOperatorRelBase) {
return ((BeamSetOperatorRelBase) node).getLimitCount(); // handle the new node type
}
throw new IllegalArgumentException("Cannot get limit count from RelNode tree with root " + node.getRelTypeName()); Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the limit-bearing node type before triggering conversion
boolean limitSupported = root instanceof BeamSortRel || root instanceof AbstractBeamCalcRel;
if (!limitSupported) throw new IllegalStateException("LIMIT shape unsupported: " + root.getRelTypeName()); Type guard
boolean hasExtractableLimit(BeamRelNode node) {
return node instanceof BeamSortRel || node instanceof AbstractBeamCalcRel;
} Try / catch
try {
sqlEnv.sqlQuery(query).evaluate();
} catch (IllegalArgumentException e) {
if (e.getMessage().startsWith("Cannot get limit count from RelNode tree")) {
// fall back to a query without the unsupported LIMIT wrapper or rewrite it
} else throw e;
} Prevention
- Keep LIMIT directly on top of a sort or simple projection
- Test LIMIT queries against all shapes used in production
- Pin Beam versions so planner node shapes are known
When it happens
Trigger: Running a Beam SQL query with LIMIT whose top node above the sort is neither BeamSortRel nor AbstractBeamCalcRel, e.g. LIMIT combined with operators not yet handled by getLimitCount.
Common situations: Queries like SELECT ... LIMIT n wrapped by other relational operators (aggregates, sets, joins) so the converter sees an unsupported RelNode root; usually surfaced when enabling an enumerable-converter-based execution path.
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
- Attempting to create database
- Attempting to 'USE CATALOG
- Cannot get column index from
- CEP operation is not recognized
- CROSS JOIN, JOIN ON FALSE is not supported!
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5681dd1c26000c62.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamEnumerableConverter.java:428
public void processElement(@SuppressWarnings("unused") ProcessContext context) {
rows.inc();
}
}
private static boolean isLimitQuery(BeamRelNode node) {
return (node instanceof BeamSortRel && ((BeamSortRel) node).isLimitOnly())
|| (node instanceof AbstractBeamCalcRel
&& ((AbstractBeamCalcRel) node).isInputSortRelAndLimitOnly());
}
private static int getLimitCount(BeamRelNode node) {
if (node instanceof BeamSortRel) {
return ((BeamSortRel) node).getCount();
} else if (node instanceof AbstractBeamCalcRel) {
return ((AbstractBeamCalcRel) node).getLimitCountOfSortRel();
}
throw new IllegalArgumentException(
"Cannot get limit count from RelNode tree with root " + node.getRelTypeName());
}
private static boolean containsUnboundedPCollection(Pipeline p) {
class BoundednessVisitor extends PipelineVisitor.Defaults {
IsBounded boundedness = IsBounded.BOUNDED;
@Override
public void visitValue(PValue value, Node producer) {
if (value instanceof PCollection) {
boundedness = boundedness.and(((PCollection) value).isBounded());
}
}
}
BoundednessVisitor visitor = new BoundednessVisitor();
p.traverseTopologically(visitor);
return visitor.boundedness == IsBounded.UNBOUNDED;View on GitHub (pinned to 12126d8942)