apache/beam · error · UnsupportedOperationException

Cannot access OnWindowExpirationContext outside of…

Error message

Cannot access OnWindowExpirationContext outside of @OnWindowExpiration methods.

What it means

This accessor supplies a DoFn<InputT, OutputT>.OnWindowExpirationContext, which is only valid while the harness executes a method annotated with @OnWindowExpiration. At all other times (element processing, timers, bundle lifecycle) there is no window-expiration context, so FnApiDoFnRunner throws UnsupportedOperationException. Note the message says 'methods' (plural) — the same guard covers every non-expiration lifecycle phase.

Solutions

  1. Access onWindowExpirationContext only from a method annotated with @OnWindowExpiration.
  2. Use ProcessContext (or the OnTimerContext inside @OnTimer) for all other lifecycle phases.
  3. Confirm the Fn API harness in your Beam version supports @OnWindowExpiration; if not, use timers (@OnTimer with a large TTL) or GC-triggers instead of window expiration callbacks.
  4. If you need expiration-like cleanup, encode it via timer APIs or window triggering rather than requesting the expiration context from element code.

Example fix

// before
@ProcessElement
public void processElement(ProcessContext c) {
  var ec = c.onWindowExpirationContext(myDoFn); // throws
}
// after
@OnWindowExpiration
public void onWindowExpiration(OnWindowExpirationContext c) {
  // valid only here
}
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(c instanceof DoFn.OnWindowExpirationContext)) {
  throw new IllegalStateException("onWindowExpirationContext requested outside @OnWindowExpiration");
}

Type guard

static boolean isOnWindowExpirationContext(DoFn.ProcessContext c) {
  return c instanceof DoFn.OnWindowExpirationContext;
}

Try / catch

try {
  DoFn.OnWindowExpirationContext ec = runner.onWindowExpirationContext(doFn);
  // use ec
} catch (UnsupportedOperationException e) {
  // not in @OnWindowExpiration; use ProcessContext or timer-based cleanup
}

Prevention

When it happens

Trigger: Calling context.onWindowExpirationContext(doFn) from @ProcessElement, @OnTimer, @StartBundle/@FinishBundle, or anywhere other than a @OnWindowExpiration-annotated method; framework code resolving the context for the wrong lifecycle callback.

Common situations: Implementing @OnWindowExpiration on a runner/harness combination that does not yet support it and probing the context elsewhere; generic DoFn helper code that requests all context variants; version mismatches where window-expiration support was added to the DoFn API but the harness path throws outside the proper callback.

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

Appendix: source

Thrown at sdks/java/harness/src/main/java/org/apache/beam/fn/harness/FnApiDoFnRunner.java:2218

    public BundleFinalizer bundleFinalizer() {
      return bundleFinalizer;
    }

    @Override
    public Object restriction() {
      return currentRestriction;
    }

    @Override
    public DoFn<InputT, OutputT>.OnTimerContext onTimerContext(DoFn<InputT, OutputT> doFn) {
      throw new UnsupportedOperationException(
          "Cannot access OnTimerContext outside of @OnTimer methods.");
    }

    @Override
    public DoFn<InputT, OutputT>.OnWindowExpirationContext onWindowExpirationContext(
        DoFn<InputT, OutputT> doFn) {
      throw new UnsupportedOperationException(
          "Cannot access OnWindowExpirationContext outside of @OnWindowExpiration methods.");
    }

    @Override
    public RestrictionTracker<?, ?> restrictionTracker() {
      return currentTracker;
    }

    @Override
    public PipelineOptions getPipelineOptions() {
      return pipelineOptions;
    }

    @Override
    public PipelineOptions pipelineOptions() {
      return pipelineOptions;
    }

View on GitHub (pinned to 12126d8942)