apache/beam · error · UnsupportedOperationException
Output from FinishBundle for SDF is not supported in naive i
Error message
Output from FinishBundle for SDF is not supported in naive implementation
What it means
SplittableParDoNaiveBounded's FinishBundle output receiver does not support emitting elements when a bundle finishes. The naive SDF implementation only supports output during ProcessElement, so any attempt to emit from finishBundle is rejected. This is an intentional limitation of this portability fallback path.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/SplittableParDoNaiveBounded.java:418
}
@FinishBundle
public void finishBundle(FinishBundleContext c) {
invoker.invokeFinishBundle(
new BaseArgumentProvider<InputT, OutputT>() {
@Override
public DoFn<InputT, OutputT>.FinishBundleContext finishBundleContext(
DoFn<InputT, OutputT> doFn) {
return new DoFn<InputT, OutputT>.FinishBundleContext() {
@Override
public PipelineOptions getPipelineOptions() {
return c.getPipelineOptions();
}
@Override
public void output(
@Nullable OutputT output, Instant timestamp, BoundedWindow window) {
throw new UnsupportedOperationException(
"Output from FinishBundle for SDF is not supported in naive implementation");
}
@Override
public <T> void output(
TupleTag<T> tag, T output, Instant timestamp, BoundedWindow window) {
throw new UnsupportedOperationException(
"Output from FinishBundle for SDF is not supported in naive implementation");
}
};
}
@Override
public PipelineOptions pipelineOptions() {
return c.getPipelineOptions();
}
@OverrideView on GitHub (pinned to 12126d8942)
Solutions
- Remove the c.output(...) call from the @FinishBundle method and emit elements during @ProcessElement instead
- Use a runner/translation that fully supports SDF finishBundle output instead of the naive implementation
- Restructure the pipeline so pending outputs are buffered and emitted in the next processElement invocation
Example fix
// before
@FinishBundle
public void finish(FinishBundleContext c) {
c.output(result, timestamp, window); // throws
}
// after
@ProcessElement
public void process(ProcessContext c) {
emitBuffered(c); // emit only from processElement
} Defensive patterns
Strategy: validation
Validate before calling
if (doFn.getClass().getDeclaredMethodsWithAnnotation(FinishBundle.class).length > 0
&& finishBundleEmitsOutput(doFn)) {
throw new IllegalStateException("FinishBundle must not emit output under naive SDF implementation");
} Try / catch
try { pipeline.run(); } catch (UnsupportedOperationException e) {
if (e.getMessage().contains("FinishBundle for SDF")) { /* restructure DoFn to emit in ProcessElement */ }
else throw e;
} Prevention
- Never call c.output(...) inside @FinishBundle of a splittable DoFn
- Check runner SDF support before relying on finishBundle emissions
- Emit pending results at the start of the next @ProcessElement instead
When it happens
Trigger: A DoFn using @FinishBundle that calls c.output(...) while being executed via the naive bounded SDF translation path (e.g. a runner using SplittableParDoNaiveBounded for splittable DoFns).
Common situations: Running an SDF pipeline on a runner that falls back to the naive SplittableParDo implementation; a DoFn emits final aggregation results in finishBundle and is accidentally turned into an SDF (e.g. via splittable DoFn annotations or runner translation).
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
- +fieldType.getTypeName()+ is not supported
- %s.verifyCompatibility() should never be called. It is a pri
- %s.getSideInputWindow() should never be called. It is a priv
- @WatermarkEstimatorState parameters are not supported.
- Unexpected StandardResolveOptions %s
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/4e71e67137f63632.
Report an issue: GitHub.