apache/beam · error · UnsupportedOperationException

Tagged output not supported in FinishBundleContext for Async

Error message

Tagged output not supported in FinishBundleContext for AsyncWrapper

What it means

Beam's FinishBundleContext supports tagged output via TupleTag, but AsyncWrapper's FinishBundle path does not wire additional output tags, so output(TupleTag, ...) unconditionally throws UnsupportedOperationException. Only the untagged output(output, timestamp, window) is supported on this wrapper.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/AsyncWrapper.java:444

    }

    @Override
    public PipelineOptions getPipelineOptions() {
      PipelineOptions options = pipelineOptions;
      if (options == null) {
        throw new IllegalStateException("PipelineOptions not set");
      }
      return options;
    }

    @Override
    public void output(OutputT output, Instant timestamp, BoundedWindow window) {
      receiver.outputWithTimestamp(output, timestamp);
    }

    @Override
    public <T> void output(TupleTag<T> tag, T output, Instant timestamp, BoundedWindow window) {
      throw new UnsupportedOperationException(
          "Tagged output not supported in FinishBundleContext for AsyncWrapper");
    }
  }

  // BaseArgumentProvider supplying element-level context to the invoker.
  private class ProcessArgProvider extends DoFnInvoker.BaseArgumentProvider<InputT, OutputT> {
    private final KV<K, InputT> element;
    private final BoundedWindow window;
    private final Instant timestamp;
    private final OutputReceiver<OutputT> receiver;

    ProcessArgProvider(
        KV<K, InputT> element,
        BoundedWindow window,
        Instant timestamp,
        OutputReceiver<OutputT> receiver) {
      this.element = element;
      this.window = window;

View on GitHub (pinned to 12126d8942)

Solutions

  1. Emit only through the untagged main output in @FinishBundle when using AsyncWrapper
  2. Move side-output emissions to @ProcessElement, or perform them outside the async wrapper
  3. Restructure the pipeline so side outputs are produced by a separate non-wrapped transform

Example fix

// before
c.output(sideTag, value, timestamp, window); // in @FinishBundle
// after
c.output(value, timestamp, window); // main output only, or emit side outputs elsewhere
Defensive patterns

Strategy: validation

Validate before calling

// Before wrapping a DoFn, check its @FinishBundle for tagged output:
for (Method m : doFn.getClass().getDeclaredMethods()) {
  if (m.isAnnotationPresent(FinishBundle.class)
      && Arrays.stream(m.getParameterTypes()).anyMatch(t -> TupleTag.class.isAssignableFrom(t))) {
    throw new IllegalArgumentException("DoFn uses tagged output in FinishBundle; incompatible with AsyncWrapper");
  }
}

Prevention

When it happens

Trigger: The wrapped DoFn's @FinishBundle method calls c.output(someTupleTag, value, timestamp, window), or the DoFn declares additional outputs that the finish-bundle logic tries to emit through.

Common situations: Migrating an existing DoFn with side outputs to be wrapped by AsyncWrapper; generic DoFn utilities that always use the tagged overload.

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/9969cf907f4a012b. Report an issue: GitHub.