apache/beam · error · UnsupportedOperationException

@WatermarkEstimatorState parameters are not supported.

Error message

@WatermarkEstimatorState parameters are not supported.

What it means

The naive bounded SDF implementation does not expose watermark estimator state to the DoFn. watermarkEstimatorState() on NestedProcessContext always throws, because this fallback path cannot reconstruct per-element watermark estimator state.

Source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/util/construction/SplittableParDoNaiveBounded.java:725

      @Override
      public @Nullable String currentRecordId(DoFn<InputT, OutputT> doFn) {
        return outerContext.currentRecordId();
      }

      @Override
      public @Nullable Long currentRecordOffset(DoFn<InputT, OutputT> doFn) {
        return outerContext.currentRecordOffset();
      }

      @Override
      public Instant fireTimestamp(DoFn<InputT, OutputT> doFn) {
        throw new IllegalStateException();
      }

      @Override
      public Object watermarkEstimatorState() {
        throw new UnsupportedOperationException(
            "@WatermarkEstimatorState parameters are not supported.");
      }

      @Override
      public WatermarkEstimator<?> watermarkEstimator() {
        return watermarkEstimator;
      }

      // ----------- Unsupported methods --------------------
      @Override
      public DoFn<InputT, OutputT>.StartBundleContext startBundleContext(
          DoFn<InputT, OutputT> doFn) {
        throw new IllegalStateException();
      }

      @Override
      public DoFn<InputT, OutputT>.FinishBundleContext finishBundleContext(
          DoFn<InputT, OutputT> doFn) {

View on GitHub (pinned to 12126d8942)

Solutions

  1. Remove the @WatermarkEstimatorState parameter from the DoFn signature
  2. Run the pipeline on a runner/translation with full SDF watermark estimator support
  3. Track estimator state manually inside the DoFn's restriction/checkpoint state instead

Example fix

// before
@ProcessElement
public void process(ProcessContext c, @WatermarkEstimatorState Instant state) { ... }
// after
@ProcessElement
public void process(ProcessContext c) { ... } // state not supported here
Defensive patterns

Strategy: validation

Validate before calling

for (Method m : doFn.getClass().getDeclaredMethods()) {
  if (m.isAnnotationPresent(ProcessElement.class)) {
    for (Annotation a : m.getParameterAnnotations()) {
      if (a instanceof WatermarkEstimatorState) {
        throw new IllegalStateException("@WatermarkEstimatorState unsupported on naive SDF path");
      }
    }
  }
}

Try / catch

try { pipeline.run(); } catch (UnsupportedOperationException e) {
  if (e.getMessage().contains("@WatermarkEstimatorState")) { /* drop the parameter */ }
  else throw e;
}

Prevention

When it happens

Trigger: A splittable DoFn @ProcessElement method declares a parameter annotated with @WatermarkEstimatorState and is executed via SplittableParDoNaiveBounded.

Common situations: Migrating an SDF that tracks watermark estimator state to a runner using the naive bounded implementation; adding @WatermarkEstimatorState parameters for self-checkpointing SDFs on runners that lack full support.

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/d18a5a3d93087f82. Report an issue: GitHub.