apache/beam · error · java.lang.UnsupportedOperationException
`ORDER BY` is only supported for %s, actual windowing strate
Error message
`ORDER BY` is only supported for %s, actual windowing strategy: %s
What it means
Beam SQL's ORDER BY (BeamSortRel) can only operate on globally sorted data. When the upstream PCollection's windowing strategy is not GlobalWindows (e.g. fixed or sliding windows), there is no meaningful total order across windows, so the transform throws this UnsupportedOperationException during expand(). With non-global windows it only works when an explicit LIMIT with a fetch path is used.
Source
Thrown at sdks/java/extensions/sql/src/main/java/org/apache/beam/sdk/extensions/sql/impl/rel/BeamSortRel.java:204
// There is a need to separate ORDER BY LIMIT and LIMIT:
// - GroupByKey (used in Top) is not allowed on unbounded data in global window so ORDER BY
// ... LIMIT
// works only on bounded data.
// - Just LIMIT operates on unbounded data, but across windows.
if (fieldIndices.isEmpty()) {
// TODO(https://github.com/apache/beam/issues/19075)
// Figure out which operations are per-window and which are not.
return upstream
.apply(Window.into(new GlobalWindows()))
.apply(new LimitTransform<>(startIndex))
.setRowSchema(CalciteUtils.toSchema(getRowType()));
} else {
WindowingStrategy<?, ?> windowingStrategy = upstream.getWindowingStrategy();
if (!(windowingStrategy.getWindowFn() instanceof GlobalWindows)) {
throw new UnsupportedOperationException(
String.format(
"`ORDER BY` is only supported for %s, actual windowing strategy: %s",
GlobalWindows.class.getSimpleName(), windowingStrategy));
}
// When no limit is specified (count == -1), we must sort the entire dataset.
// To achieve this globally, we key all rows by a single dummy key, group them together
// using GroupByKey to ensure they are processed together, and then sort them in-memory
// via SortInMemoryFn. Note: This can be memory-intensive for large datasets. It should
// only be done as a final step when the remaining data is small
if (count == -1) {
BeamSqlRowComparator comparator =
new BeamSqlRowComparator(fieldIndices, orientation, nullsFirst);
return upstream
.apply("WithDummyKey", WithKeys.of("DummyKey"))
.apply("GroupByKey", GroupByKey.create())
.apply("SortInMemory", ParDo.of(new SortInMemoryFn(comparator)))
.setRowSchema(CalciteUtils.toSchema(getRowType()));View on GitHub (pinned to 12126d8942)
Solutions
- Remove ORDER BY, or apply it after re-windowing the data into GlobalWindows (e.g. via a windowing transform / aggregate first).
- Add a LIMIT (ORDER BY ... LIMIT n) so BeamSortRel can use the supported limited path if applicable.
- Aggregate/window the streaming data into a bounded result (e.g. GlobalWindows via Window.into(GlobalWindows()) after a trigger) before sorting.
- Perform the sort downstream in a batch job or in the sink instead of inside the streaming SQL query.
Example fix
// before
PCollection<Row> sorted = windowed.apply(SqlTransform.query("SELECT * FROM t ORDER BY x"));
// after
PCollection<Row> global = windowed.apply(Window.<Row>into(new GlobalWindows()).triggering(AfterWatermark.pastEndOfWindow()).withAllowedLateness(Duration.ZERO).discardingFiredPanes());
PCollection<Row> sorted = global.apply(SqlTransform.query("SELECT * FROM PCOLLECTION ORDER BY x")); Defensive patterns
Strategy: validation
Validate before calling
WindowingStrategy<?, ?> ws = upstream.getWindowingStrategy(); if (hasOrderBy && !(ws.getWindowFn() instanceof GlobalWindows) && !hasLimit) { throw new IllegalArgumentException("ORDER BY requires GlobalWindows or a LIMIT"); } Type guard
boolean sortable = !(windowingStrategy.getWindowFn() instanceof GlobalWindows) ? hasLimit : true;
Try / catch
try { result = pc.apply(SqlTransform.query(sql)); } catch (UnsupportedOperationException e) { if (e.getMessage().contains("ORDER BY")) { /* re-window to GlobalWindows or add LIMIT */ } else { throw e; } } Prevention
- Only use ORDER BY on GlobalWindows PCollections (default for batch)
- Re-window to GlobalWindows before sorting streaming data
- Use ORDER BY ... LIMIT n for the supported limited path in streaming
- Aggregate first, then sort the small bounded result
When it happens
Trigger: Running a SQL query with ORDER BY over a streaming/windowed PCollection whose windowFn is not GlobalWindows and without a limit allowing the early-limit path; thrown from BeamSortRel.expand().
Common situations: ORDER BY on a Pub/Sub/Kafka-backed table (streaming, windowed), or on a batch table that was re-windowed before the sort; users expect SQL ORDER BY to work anywhere but it needs a single global window (or a LIMIT).
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
- Please explicitly specify windowing in SQL query using HOP/T
- GroupByKey cannot be applied to non-bounded PCollection in t
- Unknown window function ${simpleName}
- WindowFns must match for a bounded-vs-bounded/unbounded-vs-u
- Joining unbounded PCollections is currently only supported f
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/2b63c05ff63da191.
Report an issue: GitHub.