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
- Access onWindowExpirationContext only from a method annotated with @OnWindowExpiration.
- Use ProcessContext (or the OnTimerContext inside @OnTimer) for all other lifecycle phases.
- 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.
- 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
- Request OnWindowExpirationContext only from @OnWindowExpiration methods
- Verify your Beam Fn API harness version supports @OnWindowExpiration before adopting it
- Prefer timers or window triggers for cleanup logic if support is uncertain
- Keep expiration logic isolated so generic context helpers never touch it
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
- Cannot access OnTimerContext outside of @OnTimer methods.
- BoundedWindow unsupported in
- Cannot access fire timestamp outside of @OnTimer method.
- Cannot access time domain outside of @ProcessTimer method.
- Cannot access timerId as parameter outside of @OnTimer…
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)