apache/beam · error · UnsupportedOperationException

OnTimerContext unsupported in

Error message

OnTimerContext unsupported in %s

What it means

The placeholder DoFnInvoker implementation throws UnsupportedOperationException when OnTimerContext is requested. OnTimerContext is only valid while dispatching an @OnTimer callback, and the stub invoker never provides one. getErrorContext() embeds the DoFn and call-site information in the message.

Solutions

  1. Build the invoker with DoFnInvokers.newInvoker/tryInvokeFor so the accessor is implemented
  2. Request OnTimerContext only from the timer dispatch path
  3. If writing a runner, override onTimerContext in your invoker subclass to supply the runner's timer context

Example fix

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

Strategy: validation

Validate before calling

if (invoker.getClass().getSimpleName().contains("Unsupported")) {
  throw new IllegalStateException("Stub invoker cannot provide OnTimerContext");
}

Type guard

boolean supportsTimerContext(DoFnInvoker<?, ?> i) {
  return i.getClass() != DoFnInvoker.BaseDoFnInvoker.class;
}

Try / catch

try {
  timerCtx = invoker.onTimerContext(doFn);
} catch (UnsupportedOperationException e) {
  throw new IllegalStateException("Runner does not supply OnTimerContext", e);
}

Prevention

When it happens

Trigger: Invoking onTimerContext(...) (or onWindowExpirationContext(...) per the stub's chain of accessors) on an invoker instance that did not override that accessor — i.e. any invoker not built through DoFnInvokers' generated/reflective path.

Common situations: Custom runner code driving timers without a runner-provided invoker; unit tests instantiating the abstract base directly; accessing a timer context from a method that is not @OnTimer/@OnWindowExpiration.

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

Appendix: source

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

    }

    @Override
    public DoFn<InputT, OutputT>.FinishBundleContext finishBundleContext(
        DoFn<InputT, OutputT> doFn) {
      throw new UnsupportedOperationException(
          String.format("FinishBundleContext unsupported in %s", getErrorContext()));
    }

    @Override
    public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT> doFn) {
      throw new UnsupportedOperationException(
          String.format("OnTimerContext unsupported in %s", getErrorContext()));
    }

    @Override
    public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
        DoFn<InputT, OutputT> doFn) {
      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(

View on GitHub (pinned to 12126d8942)