apache/beam · error · UnsupportedOperationException
Cannot access timerId as parameter outside of @OnTimer metho
Error message
Cannot access timerId as parameter outside of @OnTimer method.
What it means
The timerId context parameter is only available inside @OnTimer callbacks. DoFnTester's ProcessContext throws UnsupportedOperationException when a @ProcessElement method requests timerId, since no timer is firing during element processing.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/DoFnTester.java:321
@Override
public InputT element(DoFn<InputT, OutputT> doFn) {
return processContext.element();
}
@Override
public Object key() {
throw new UnsupportedOperationException(
"Cannot access key as parameter outside of @OnTimer method.");
}
@Override
public Instant timestamp(DoFn<InputT, OutputT> doFn) {
return processContext.timestamp();
}
@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(
"Not expected to access TimeDomain from @ProcessElement");
}
@Override
public OutputReceiver<OutputT> outputReceiver(DoFn<InputT, OutputT> doFn) {
return DoFnOutputReceivers.windowedReceiver(processContext, builderSupplier, null);
}
@Override
public MultiOutputReceiver taggedOutputReceiver(DoFn<InputT, OutputT> doFn) {
return DoFnOutputReceivers.windowedMultiReceiver(
processContext, builderSupplier, null);View on GitHub (pinned to 12126d8942)
Solutions
- Move the timerId parameter into the @OnTimer method only
- Pass the timer id as a constant/field (it's a compile-time known id) rather than a context parameter in processElement
- Refactor shared logic to not depend on timer identity outside timer callbacks
Example fix
// before
@ProcessElement public void process(ProcessContext c, @TimerId String id) {...}
// after
private static final String TIMER_ID = "myTimer";
@OnTimer(TIMER_ID) public void onTimer(@TimerId String id) {...} Defensive patterns
Strategy: type-guard
Type guard
// TimerId only injectable in @OnTimer callbacks boolean inOnTimer = method.isAnnotationPresent(OnTimer.class);
Try / catch
try {
tester.processElement();
} catch (UnsupportedOperationException e) {
// @TimerId parameter used in @ProcessElement
} Prevention
- Timer ids are compile-time constants; reference the constant instead of a context parameter
- Keep @OnTimer-specific parameters out of @ProcessElement signatures
When it happens
Trigger: Declaring a String timerId parameter (annotated as TimerId) in a @ProcessElement method run through DoFnTester.
Common situations: Copy-pasting @OnTimer signatures into @ProcessElement; DoFns sharing a helper that takes timerId and is also called from processElement.
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
- Not expected to access TimeDomain from @ProcessElement
- Not expected to access DoFn.StartBundleContext from @Process
- Not expected to access DoFn.FinishBundleContext from @Proces
- Cannot access key as parameter outside of @OnTimer method.
- Not expected to access Restriction from a regular DoFn in Do
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/9608a5955243c34e.
Report an issue: GitHub.