apache/beam · error · java.lang.UnsupportedOperationException
Cannot explodeWindows() on WindowedValue builder; use…
Error message
Cannot explodeWindows() on WindowedValue builder; use build().explodeWindows()
What it means
The WindowedValue.Builder intentionally does not support explodeWindows(); splitting a builder into per-window builders is undefined. Callers must first build() the WindowedValue and then call explodeWindows() on the resulting value. Thrown as UnsupportedOperationException to fail fast on misuse of the fluent builder API.
Solutions
- Call build() first: windowedValue = builder.build(); then windowedValue.explodeWindows()
- Adjust helper methods to accept WindowedValue<T>, not Builder<T>
- Restructure the pipeline so window explosion happens after the value is fully constructed
Example fix
// before Collection<Builder<T>> parts = builder.explodeWindows(); // after Collection<WindowedValue<T>> parts = builder.build().explodeWindows();
Defensive patterns
Strategy: try-catch
Validate before calling
if (obj instanceof WindowedValues.Builder) { throw new IllegalArgumentException("call build() before explodeWindows()"); } Type guard
boolean isExplodable(Object o) { return o instanceof WindowedValue && !(o instanceof WindowedValues.Builder); } Try / catch
try { parts = x.explodeWindows(); } catch (UnsupportedOperationException e) { if (x instanceof WindowedValues.Builder) parts = ((WindowedValues.Builder<T>) x).build().explodeWindows(); else throw e; } Prevention
- Treat Builder as write-only; always build() before read/transform operations
- Type helper methods as WindowedValue<T> rather than Builder<T>
- Check the API surface of builder classes when refactoring from value classes
When it happens
Trigger: Calling builder.explodeWindows() on a WindowedValues.Builder instance (obtained via WindowedValue.of(...)...inGlobalWindow().withValue(...) etc.) instead of on the built WindowedValue.
Common situations: Refactoring code from WindowedValue to its builder API and assuming builder parity; generic helper methods accepting either a WindowedValue or a Builder; fluent chains that keep the builder in scope.
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
- BoundedWindow unsupported in
- Cannot access fire timestamp outside of @OnTimer method.
- Cannot access OnTimerContext outside of @OnTimer methods.
- Cannot access OnWindowExpirationContext outside of…
- Cannot access time domain outside of @ProcessTimer method.
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bcd587c23335e860.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/values/WindowedValues.java:242
public @Nullable Long getRecordOffset() {
return recordOffset;
}
@Override
public CausedByDrain causedByDrain() {
checkStateNotNull(causedByDrain, "CausedByDrain not set");
return causedByDrain;
}
@Override
public ValueKind getValueKind() {
checkStateNotNull(valueKind, "ValueKind not set");
return valueKind;
}
@Override
public Collection<Builder<T>> explodeWindows() {
throw new UnsupportedOperationException(
"Cannot explodeWindows() on WindowedValue builder; use build().explodeWindows()");
}
@Override
@Pure
public <OtherT> Builder<OtherT> withValue(OtherT newValue) {
// because of erasure, this type system lie is safe
return ((Builder<OtherT>) builder(this)).setValue(newValue);
}
@Override
public void output() {
try {
checkStateNotNull(receiver, "A WindowedValueReceiver must be set via setReceiver()")
.output(build());
} catch (Exception exc) {
if (exc instanceof RuntimeException) {
throw (RuntimeException) exc;View on GitHub (pinned to 12126d8942)