apache/beam · error · IllegalStateException
GroupByKey cannot be applied to non-bounded PCollection in t
Error message
GroupByKey cannot be applied to non-bounded PCollection in the GlobalWindow without a trigger. Use a Window.into or Window.triggering transform prior to GroupByKey.
What it means
GroupByKey in the GlobalWindow with the DefaultTrigger never fires on an unbounded stream because the end-of-global-window watermark is never reached, so results would never be emitted. Beam rejects this configuration up front in applicableTo() with an IllegalStateException.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/GroupByKey.java:180
/**
* For Beam internal use only. Tells runner that this is a GBK wrapped around of a
* GroupByEncryptedKey
*/
public boolean surroundsGBEK() {
return this.surroundsGBEK;
}
/////////////////////////////////////////////////////////////////////////////
public static void applicableTo(PCollection<?> input) {
WindowingStrategy<?, ?> windowingStrategy = input.getWindowingStrategy();
// Verify that the input PCollection is bounded, or that there is windowing/triggering being
// used. Without this, the watermark (at end of global window) will never be reached.
if (windowingStrategy.getWindowFn() instanceof GlobalWindows
&& windowingStrategy.getTrigger() instanceof DefaultTrigger
&& input.isBounded() != IsBounded.BOUNDED) {
throw new IllegalStateException(
"GroupByKey cannot be applied to non-bounded PCollection in the GlobalWindow without a"
+ " trigger. Use a Window.into or Window.triggering transform prior to GroupByKey.");
}
// Validate that the trigger does not finish before garbage collection time
if (!triggerIsSafe(windowingStrategy)) {
throw new IllegalArgumentException(
String.format(
"Unsafe trigger '%s' may lose data, did you mean to wrap it in"
+ "`Repeatedly.forever(...)`?%nSee "
+ "https://s.apache.org/finishing-triggers-drop-data "
+ "for details.",
windowingStrategy.getTrigger()));
}
}
@Override
public void validate(View on GitHub (pinned to 12126d8942)
Solutions
- Add a windowing transform before GroupByKey, e.g. input.apply(Window.into(FixedWindows.of(Duration.standardMinutes(1))))
- Add a non-default triggering strategy, e.g. Window.triggering(Repeatedly.forever(AfterProcessingTime.pastFirstElementInPane().plusDelayOf(Duration.standardSeconds(30))))
- Ensure the source PCollection is truly bounded if you intended a batch pipeline (check the connector's isBounded)
- For streaming aggregation, consider GroupIntoBatches or Beam's streaming SQL/MBR alternatives that handle unbounded grouping
Example fix
// before
unboundedPCollection.apply(GroupByKey.create());
// after
unboundedPCollection
.apply(Window.<KV<K,V>>into(FixedWindows.of(Duration.standardMinutes(1))))
.apply(GroupByKey.create()); Defensive patterns
Strategy: validation
Validate before calling
if (input.isBounded() != IsBounded.BOUNDED
&& input.getWindowingStrategy().getWindowFn() instanceof GlobalWindows
&& input.getWindowingStrategy().getTrigger() instanceof DefaultTrigger) {
throw new IllegalArgumentException("Apply Window.into/triggering before GroupByKey");
} Try / catch
try {
grouped = unbounded.apply(GroupByKey.create());
} catch (IllegalStateException e) {
if (e.getMessage().contains("non-bounded PCollection in the GlobalWindow")) { /* add windowing */ }
else throw e;
} Prevention
- Never apply raw GroupByKey directly on streaming sources
- Add Window.into(...) as the first step after any unbounded Read
- Document windowing requirements in pipeline composition utilities
When it happens
Trigger: Applying GroupByKey (directly, not inside GBK-into-Batches or with windowing) to an unbounded PCollection (streaming source such as Pub/Sub, Kafka, or an unbounded PTransform input) whose windowing strategy is GlobalWindows with the DefaultTrigger.
Common situations: Streaming pipelines that read from an unbounded source and apply GroupByKey without first calling Window.into(...); prototypes written batch-first and later repointed at a streaming source; forgetting fixed/sliding/session windows in a streaming job.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- GroupByKey cannot be applied to an unbounded PCollection wit
- Runner does not support draining.
- Distinct does not support merging windowing strategies, exce
- Inputs to Flatten had incompatible window windowFns: %s, %s
- Inputs to Flatten had incompatible triggers: %s, %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/33e3730f293d0bf6.
Report an issue: GitHub.