apache/beam · error · UnsupportedOperationException

Timer unsupported in

Error message

Timer unsupported in %s

What it means

Requesting a Timer object from the stub DoFnInvoker implementation throws UnsupportedOperationException. Timers require a runner-backed context, which the base class never supplies. getErrorContext() names the DoFn and call context.

Solutions

  1. Construct the invoker via DoFnInvokers.newInvoker/tryInvokeFor
  2. Only request Timer inside lifecycle methods whose signature includes the timer parameter
  3. Confirm the runner supports timers for this pipeline

Example fix

// before
new DoFnInvoker.BaseDoFnInvoker<T, O>(){}.timer("myTimer"); // throws
// after
DoFnInvokers.tryInvokeFor(fn).timer("myTimer");
Defensive patterns

Strategy: validation

Validate before calling

if (signature.getTimerDeclarations().containsKey(timerId)) {
  ensureInvokerSupportsTimers(invoker);
}

Type guard

boolean supportsTimers(DoFnInvoker<?, ?> i) {
  return !(i instanceof DoFnInvoker.BaseDoFnInvoker);
}

Try / catch

try {
  Timer timer = invoker.timer(timerId);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Timer unsupported for this invoker", e);
}

Prevention

When it happens

Trigger: Calling timer(timerId) on an invoker that does not override it — i.e. a placeholder invoker rather than one produced by DoFnInvokers.

Common situations: Using @TimerId with a runner lacking timer support; unit-test invokers built from the abstract base; accessing timers outside the appropriate lifecycle phase.

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

Appendix: source

Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java:470

      throw new UnsupportedOperationException(
          String.format("OnWindowExpirationContext unsupported in %s", getErrorContext()));
    }

    @Override
    public State state(String stateId, boolean alwaysFetched) {
      throw new UnsupportedOperationException(
          String.format("State unsupported in %s", getErrorContext()));
    }

    @Override
    public Timer timer(String timerId) {
      throw new UnsupportedOperationException(
          String.format("Timer unsupported in %s", getErrorContext()));
    }

    @Override
    public RestrictionTracker<?, ?> restrictionTracker() {
      throw new UnsupportedOperationException(
          String.format("RestrictionTracker unsupported in %s", getErrorContext()));
    }

    @Override
    public Object watermarkEstimatorState() {
      throw new UnsupportedOperationException(
          String.format("WatermarkEstimatorState unsupported in %s", getErrorContext()));
    }

    @Override
    public WatermarkEstimator<?> watermarkEstimator() {
      throw new UnsupportedOperationException(
          String.format("WatermarkEstimator unsupported in %s", getErrorContext()));
    }

    @Override
    public BundleFinalizer bundleFinalizer() {
      throw new UnsupportedOperationException(

View on GitHub (pinned to 12126d8942)