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

  1. Check that every fired timer corresponds to a declared @TimerId field with a matching @OnTimer method in the DoFn.
  2. Rebuild and redeploy so the pipeline graph and worker code use identical DoFn definitions.
  3. 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

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


AI-assisted analysis of apache/beam@12126d8942 (2026-09-13). Data as JSON: /api/errors/962a0536603e2bb8. Report an issue: GitHub.