apache/beam · error · IllegalArgumentException
Attempted to invoke timer ${timerId} on ${className}, but th
Error message
Attempted to invoke timer ${timerId} on ${className}, but that timer is not registered. This is the responsibility of the runner, which must only deliver registered timers. What it means
DoFnInvoker dispatches @OnTimer callbacks by timer id through generated ByteBuddy invokers. This error is thrown when a runner delivers a timer that the DoFn never declared via @TimerId/@TimerFamily, so the invoker map has no handler for that timerId or timerFamilyId.
Source
Thrown at sdks/java/core/src/main/java/org/apache/beam/sdk/transforms/reflect/ByteBuddyDoFnInvokerFactory.java:326
*/
void addOnTimerFamilyInvoker(String timerFamilyId, OnTimerInvoker onTimerInvoker) {
this.onTimerFamilyInvokers.put(timerFamilyId, onTimerInvoker);
}
@Override
public void invokeOnTimer(
String timerId,
String timerFamilyId,
DoFnInvoker.ArgumentProvider<InputT, OutputT> arguments) {
@Nullable OnTimerInvoker onTimerInvoker =
timerFamilyId.isEmpty()
? onTimerInvokers.get(timerId)
: onTimerFamilyInvokers.get(timerFamilyId);
if (onTimerInvoker != null) {
onTimerInvoker.invokeOnTimer(arguments);
} else {
throw new IllegalArgumentException(
String.format(
"Attempted to invoke timer %s on %s, but that timer is not registered."
+ " This is the responsibility of the runner, which must only deliver"
+ " registered timers.",
timerId, delegate.getClass().getName()));
}
}
@Override
public DoFn<InputT, OutputT> getFn() {
return delegate;
}
}
/** Returns the {@link DoFnInvoker} for the given {@link DoFn}. */
public <InputT, OutputT> DoFnInvoker<InputT, OutputT> newByteBuddyInvoker(
DoFnSignature signature, DoFn<InputT, OutputT> fn) {
checkArgument(View on GitHub (pinned to 12126d8942)
Solutions
- Check that every fired timer corresponds to a declared @TimerId field with a matching @OnTimer method in the DoFn.
- Rebuild and redeploy so the pipeline graph and worker code use identical DoFn definitions.
- If you own the runner, validate timer ids against DoFnSignatures before delivery and deliver only registered timers.
Example fix
// before
@ProcessElement public void process(...) { timer.set(...); } // no @TimerId declared
// after
class MyFn extends DoFn<KV<String,Long>, Long> {
@TimerId public final TimerSpec timer = TimerSpecs.timer();
@ProcessElement public void process(...) { timer.set(...); }
@OnTimer("timer") public void onTimer(...) { ... }
} Defensive patterns
Strategy: try-catch
Validate before calling
DoFnSignature sig = DoFnSignatures.getSignature(fn.getClass());
if (!sig.timerDeclarations().containsKey(timerId) && !sig.timerFamilyDeclarations().containsKey(timerFamilyId)) {
throw new IllegalArgumentException("timer not registered on " + fn.getClass());
} Try / catch
try {
invoker.invokeOnTimer(arguments);
} catch (IllegalArgumentException e) {
if (e.getMessage().contains("timer is not registered")) {
throw new IllegalStateException("graph/worker mismatch: timer " + timerId + " missing on " + fn.getClass(), e);
}
throw e;
} Prevention
- Declare every timer with @TimerId (or @TimerFamily) and match @OnTimer ids exactly.
- Rebuild and redeploy the whole pipeline after renaming timer fields so graph and worker agree.
- Custom runners should validate timer ids against DoFnSignatures before delivering.
When it happens
Trigger: A runner delivers a timer to a DoFn whose signature has no matching @TimerId (or @TimerFamily) field; timer ids drift between the job graph and the worker's copy of the code.
Common situations: Renaming a @TimerId field without redeploying so the staged graph and worker code disagree; a custom/direct runner bug delivering timers for the wrong DoFn; runner/SDK version mismatch.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Runner does not support draining.
- Class '%s' does not implement PipelineRunner. Supported pipe
- Unknown 'runner' specified '%s', supported pipeline runners
- Parameter has no schema and the input is not a simple type.
- Parameter has no schema and the input is not a primitive typ
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/962a0536603e2bb8.
Report an issue: GitHub.