apache/beam · error · UnsupportedOperationException
TimerFamily unsupported in ${context}
Error message
TimerFamily unsupported in ${context} What it means
This UnsupportedOperationException is thrown by DoFnInvoker.BaseArgumentProvider.timerFamily when a timer-family parameter is requested in a DoFn invocation context that cannot supply one. Timer families (DoFn.TimerMap / @TimerFamily) only exist while an @OnTimer method is firing, so every other context's ArgumentProvider leaves timerFamily un-overridden and inherits this throwing default. The context name is filled in by getErrorContext() so the developer can see where the illegal access happened.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/DoFnInvoker.java:330
throw new UnsupportedOperationException(
String.format("Element unsupported in %s", getErrorContext()));
}
@Override
public @Nullable Object key() {
throw new UnsupportedOperationException(
"Cannot access key as parameter outside of @OnTimer method.");
}
@Override
public @Nullable Object sideInput(String tagId) {
throw new UnsupportedOperationException(
String.format("SideInput unsupported in %s", getErrorContext()));
}
@Override
public TimerMap timerFamily(String tagId) {
throw new UnsupportedOperationException(
String.format("TimerFamily unsupported in %s", getErrorContext()));
}
@Override
public @Nullable Object schemaElement(int index) {
throw new UnsupportedOperationException(
String.format("Schema element unsupported in %s", getErrorContext()));
}
@Override
public Instant timestamp(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(
String.format("Timestamp unsupported in %s", getErrorContext()));
}
@Override
public @Nullable String currentRecordId(DoFn<InputT, OutputT> doFn) {
throw new UnsupportedOperationException(View on GitHub (pinned to 12126d8942)
Solutions
- Only request a TimerMap inside @OnTimer methods; in @ProcessElement use DoFn.ProcessContext.timer(timerId) for individual timers instead.
- Verify the parameter's annotation/context matches the method it is declared on (e.g. @TimerFamily parameters belong on @OnTimer methods).
- Check the runner's support level for timer families (RunnerDAG capability) and upgrade the runner/SDK if TimerFamily is not yet supported.
- If implementing a custom ArgumentProvider, override timerFamily(String) to return the actual TimerMap for the firing context.
Example fix
// before
@ProcessElement
public void processElement(ProcessContext c) {
c.timerFamily("cleanup").set(c.timestamp().plus(Duration.standardMinutes(5))); // throws
}
// after
@ProcessElement
public void processElement(ProcessContext c) {
c.timer("cleanup").set(c.timestamp().plus(Duration.standardMinutes(5)));
} Defensive patterns
Strategy: validation
Validate before calling
// TimerMap parameters are only valid on @OnTimer methods; check before building the pipeline. DoFnSignature sig = DoFnSignatures.getSignature(doFn.getClass()); sig.timerFamilyDeclarations(); // ensure each declaration's receiver is an OnTimerContext method
Type guard
if (context instanceof DoFn.OnTimerContext) {
// timer family access is only meaningful here
} Try / catch
try {
TimerMap timers = context.timerFamily("cleanup");
} catch (UnsupportedOperationException e) {
// not a timer-firing context; schedule timers via ProcessContext.timer() instead
} Prevention
- Use c.timer(timerId) from @ProcessElement; reserve TimerMap for @OnTimer.
- Confirm runner support for timer families before using @TimerFamily.
- Keep @TimerFamily parameters only on methods annotated @OnTimer.
When it happens
Trigger: Requesting a TimerMap (e.g. c.timerFamily("family") or an @TimerFamily annotated parameter) from a context other than a firing timer: @ProcessElement, @StartBundle, @FinishBundle, @OnWindowExpiration methods, or custom ArgumentProviders that do not override timerFamily(String).
Common situations: Trying to set/reset timers from @ProcessElement via timerFamily instead of the per-timer c.timer(...) API; declaring a TimerMap parameter on a non-@OnTimer method and letting the invoker bind it; SDK/runner mismatch where the runner's ArgumentProvider does not yet support TimerFamily (older runners or Flink/Spark versions predating timer families).
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
- FireTimestamp unsupported in %s
- CausedByDrain unsupported in %s
- Cannot access fire timestamp outside of @OnTimer method.
- Cannot access timerId as parameter outside of @OnTimer metho
- Cannot access timerId as parameter outside of @OnTimer metho
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d53fd36a3304cce5.
Report an issue: GitHub.