apache/beam · error · java.lang.UnsupportedOperationException
Does not support queries with LIMIT in toRowList.
Error message
Does not support queries with LIMIT in toRowList.
What it means
toRowList materializes the full result of a Beam SQL plan into memory, which cannot honor a LIMIT clause (the limit is not pushed through collectRows in this path). If isLimitQuery(node) detects LIMIT in the plan, it throws UnsupportedOperationException telling the caller this execution mode does not support LIMIT. Use the toEnumerable path (or remove the LIMIT) instead.
Solutions
- Use toEnumerable(options, node) instead of toRowList for queries with LIMIT
- Remove the LIMIT clause from the SQL and limit the resulting list yourself after collection
- Push the limit into the source (e.g. a filtered/limited PCollection or read with a bounded count) instead of relying on SQL LIMIT with toRowList
- Upgrade/patch BeamEnumerableConverter to support LIMIT by applying the limit to the collected list (or use the enumerable path internally)
Example fix
// before
List<Row> rows = BeamEnumerableConverter.toRowList(options, relNode); // SELECT ... LIMIT 10
// after
List<Row> rows = new ArrayList<>();
BeamEnumerableConverter.toEnumerable(options, relNode).forEach(r -> { if (rows.size() < 10) rows.add(r); }); // or drop LIMIT and slice after collection Defensive patterns
Strategy: type-guard
Validate before calling
static boolean planHasLimit(BeamRelNode node) {
for (RelNode n : node.getInputs()) { if (n instanceof BeamSortRel) return true; }
return node instanceof BeamSortRel;
} Type guard
boolean isLimitQuery(BeamRelNode node) { return node instanceof BeamSortRel || node.getInputs().stream().anyMatch(i -> i instanceof BeamSortRel); } Try / catch
try {
rows = BeamEnumerableConverter.toRowList(options, node);
} catch (UnsupportedOperationException e) {
if (e.getMessage().contains("LIMIT")) {
rows = collectViaEnumerable(node); // LIMIT-capable path, or re-run without LIMIT
} else { throw e; }
} Prevention
- Prefer toEnumerable for any query that might contain LIMIT/OFFSET
- Validate the SQL plan (look for BeamSortRel) before selecting the toRowList execution path
- Apply limits client-side on the collected rows instead of using SQL LIMIT with toRowList
- Document in test helpers which execution modes support which SQL features
When it happens
Trigger: Calling BeamEnumerableConverter.toRowList(options, node) on a BeamRelNode whose plan contains a Sort/Limit (isLimitQuery returns true) — typically a SELECT ... LIMIT N statement executed through the row-list collection path.
Common situations: Running 'SELECT * FROM t LIMIT 10' via BeamSqlCli/JDBC paths configured to use toRowList; adding LIMIT to a query in tests that use the toRowList helper; library versions where LIMIT was only supported in the enumerable (toEnumerable) execution mode.
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
- Does not support BeamIOSinkRel in toRowList.
- A 'datagen' table requires either 'rows-per-second' (for…
- Adding required columns is not yet supported. Encountered…
- ALTER is not supported for table
- Analytics Function [ ] is not supported
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/b52e7e9661eaa288.
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:162
}
public static PipelineOptions createPipelineOptions(Map<String, String> map) {
final String[] args = new String[map.size()];
int i = 0;
for (Map.Entry<String, String> entry : map.entrySet()) {
args[i++] = "--" + entry.getKey() + "=" + entry.getValue();
}
PipelineOptions options = PipelineOptionsFactory.fromArgs(args).withValidation().create();
FileSystems.setDefaultPipelineOptions(options);
options.as(ApplicationNameOptions.class).setAppName("BeamSql");
return options;
}
static List<Row> toRowList(PipelineOptions options, BeamRelNode node) {
if (node instanceof BeamIOSinkRel) {
throw new UnsupportedOperationException("Does not support BeamIOSinkRel in toRowList.");
} else if (isLimitQuery(node)) {
throw new UnsupportedOperationException("Does not support queries with LIMIT in toRowList.");
}
return collectRows(options, node).stream().collect(Collectors.toList());
}
static Enumerable<Object> toEnumerable(PipelineOptions options, BeamRelNode node) {
if (node instanceof BeamIOSinkRel) {
return count(options, node);
} else if (isLimitQuery(node)) {
return limitCollect(options, node);
}
return Linq4j.asEnumerable(rowToAvaticaAndUnboxValues(collectRows(options, node)));
}
private static PipelineResult limitRun(
PipelineOptions options,
BeamRelNode node,
DoFn<Row, Void> doFn,
Queue<Row> values,View on GitHub (pinned to 12126d8942)