apache/beam · error · UnsupportedOperationException
Cannot access time domain outside of @ProcessTimer method.
Error message
Cannot access time domain outside of @ProcessTimer method.
What it means
FnApiDoFnRunner.timeDomain() returns the TimeDomain (event time vs processing time) of the currently firing timer. Because timer firing is delivered via the runner's @ProcessTimer handling, this value only exists inside a timer callback; the accessor throws UnsupportedOperationException everywhere else. The message references @ProcessTimer, the internal runner entry point for fired timers (user code sees this as @OnTimer).
Solutions
- Access timeDomain() only from inside a @OnTimer method (OnTimerContext).
- If you need domain-dependent behavior for elements, decide it explicitly in your pipeline logic (you already chose the domain when setting the timer via Timer.withTimeDomain / in event-time vs processing-time timer creation).
- Split element-path and timer-path code so timer-only context parameters (TimeDomain, TimerId, fireTimestamp) are never reachable from the element path.
- Update helpers to take TimeDomain as an explicit parameter from the @OnTimer method.
Example fix
// before
@ProcessElement
public void processElement(ProcessContext c) {
TimeDomain d = c.timeDomain(); // throws
}
// after
@OnTimer("tick")
public void onTimer(OnTimerContext c) {
TimeDomain d = c.timeDomain(); // valid here
} Defensive patterns
Strategy: validation
Validate before calling
TimeDomain domain = null;
if (c instanceof DoFn.OnTimerContext) {
domain = ((DoFn.OnTimerContext) c).timeDomain();
} else {
// element path: decide domain from your own timer configuration
domain = myTimerIsProcessingTime ? TimeDomain.PROCESSING_TIME : TimeDomain.EVENT_TIME;
} Type guard
static boolean canReadTimeDomain(DoFn.ProcessContext c) {
return c instanceof DoFn.OnTimerContext;
} Try / catch
try {
TimeDomain d = ((DoFn.OnTimerContext) c).timeDomain();
} catch (UnsupportedOperationException e) {
TimeDomain d = configuredDomain; // from Timer.withTimeDomain choice
} Prevention
- Read timeDomain() only inside @OnTimer
- You already picked the domain when creating the timer; store it if needed elsewhere
- Split event-time and processing-time timer handlers into separate methods
- Pin Beam version and check DoFn parameter-binding docs for the harness in use
When it happens
Trigger: Calling context.timeDomain() (or binding a TimeDomain parameter) from @ProcessElement/@StartBundle/@FinishBundle instead of a @OnTimer method; timer-family parameter resolution wiring TimeDomain into a non-timer invocation inside the Fn API harness.
Common situations: Code migrated from runners where TimeDomain was accessible more broadly; generic context helper methods that read timeDomain unconditionally; mixing event-time and processing-time timer handling and probing the domain from the wrong 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 fire timestamp outside of @OnTimer method.
- Cannot access OnTimerContext outside of @OnTimer methods.
- Cannot access timerId as parameter outside of @OnTimer…
- CausedByDrain unsupported in
- FireTimestamp unsupported in
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/869d69b34a65a6e7.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/java/harness/src/main/java/org/apache/beam/fn/harness/FnApiDoFnRunner.java:2078
public @Nullable Long currentRecordOffset(DoFn<InputT, OutputT> doFn) {
return currentRecordOffset();
}
@Override
public Instant fireTimestamp(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access fire timestamp outside of @OnTimer method.");
}
@Override
public String timerId(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access timerId as parameter outside of @OnTimer method.");
}
@Override
public TimeDomain timeDomain(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
"Cannot access time domain outside of @ProcessTimer method.");
}
@Override
public OutputReceiver<OutputT> outputReceiver(DoFn<InputT, OutputT> doFn) {
return this;
}
@Override
// OutputT == RestrictionT
public void output(OutputT output) {
OutputReceiver.super.output(output);
}
private final OutputReceiver<Row> mainRowOutputReceiver =
mainOutputSchemaCoder == null
? null
: new OutputReceiver<Row>() {View on GitHub (pinned to 12126d8942)