apache/beam · error · UnsupportedOperationException

Should not call getContinuationTrigger

Error message

Should not call getContinuationTrigger(List<Trigger>)

What it means

AfterWatermark's continuation trigger computation intentionally does not use the generic getContinuationTrigger(List<Trigger>) path; it builds continuations from its early/late sub-triggers directly. Calling the list-based method is a programming error, so Beam throws UnsupportedOperationException with this message.

Solutions

  1. Call the no-argument getContinuationTrigger() instead; AfterWatermark composes early/late continuations itself
  2. Remove custom code that invokes the protected List-based method; it's not part of AfterWatermark's supported API
  3. If you need the combined continuation, use AfterWatermark.pastEarlyAndLateTriggers(...).getContinuationTrigger()
  4. When writing generic trigger utilities, special-case AfterWatermark or rely on the public continuation API

Example fix

// before
Trigger cont = afterWatermark.getContinuationTrigger(List.of(cont1, cont2));

// after
Trigger cont = afterWatermark.getContinuationTrigger();
Defensive patterns

Strategy: type-guard

Validate before calling

// Use only the public continuation API
if (trigger instanceof AfterWatermark) {
  Trigger cont = ((AfterWatermark) trigger).getContinuationTrigger();
}

Type guard

static Trigger safeContinuation(Trigger t) {
  return t instanceof AfterWatermark
      ? ((AfterWatermark) t).getContinuationTrigger()
      : t.getContinuationTrigger();
}

Try / catch

try {
  trigger.getContinuationTrigger();
} catch (UnsupportedOperationException e) {
  // switch to the no-arg getContinuationTrigger()
}

Prevention

When it happens

Trigger: Calling getContinuationTrigger(List<Trigger>) on an AfterWatermark instance directly, or via reflection/framework code that invokes the protected generic path instead of getContinuationTrigger().

Common situations: Custom trigger frameworks iterating triggers and calling the generic continuation API; subclassing Trigger and reusing AfterWatermark in code paths that expect the list-based method to work; testing trigger internals.

Related errors


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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/windowing/AfterWatermark.java:118

    public AfterWatermarkEarlyAndLate withLateFirings(OnceTrigger lateTrigger) {
      return new AfterWatermarkEarlyAndLate(earlyTrigger, lateTrigger);
    }

    @Override
    public <OutputT> OutputT accept(TriggerVisitor<OutputT> visitor) {
      return visitor.visit(this);
    }

    @Override
    public Trigger getContinuationTrigger() {
      return new AfterWatermarkEarlyAndLate(
          earlyTrigger.getContinuationTrigger(),
          lateTrigger == null ? null : lateTrigger.getContinuationTrigger());
    }

    @Override
    protected Trigger getContinuationTrigger(List<Trigger> continuationTriggers) {
      throw new UnsupportedOperationException(
          "Should not call getContinuationTrigger(List<Trigger>)");
    }

    @Override
    public Instant getWatermarkThatGuaranteesFiring(BoundedWindow window) {
      // Even without an early or late trigger, we'll still produce a firing at the watermark.
      return window.maxTimestamp();
    }

    /** Returns true if there is no late firing set up, otherwise false. */
    @Override
    public boolean mayFinish() {
      return lateTrigger == null;
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder(TO_STRING);

View on GitHub (pinned to 12126d8942)