apache/beam · error · ValueError
DoFn %r has a TimerSpec without an associated on_timer…
Error message
DoFn %r has a TimerSpec without an associated on_timer callback: %s.
What it means
Apache Beam raises this ValueError when a DoFn declares a TimerSpec whose _attached_callback is empty/None, meaning no on_timer callback was wired to the timer. A timer with no callback can never be handled when it fires, so the pipeline is rejected during validate_stateful_dofn. This usually means the TimerSpec was created without the on_timer= argument (or with a misspelled callback reference that didn't bind).
Solutions
- Pass the on_timer= method to TimerSpec: TimerSpec('name', on_timer=MyDoFn.process_timer).
- Fix typos in the callback reference so the timer's _attached_callback is set.
- Remove the TimerSpec entirely if the timer is no longer used.
Example fix
// before
EXPIRY_TIMER = TimerSpec('expiry') # no on_timer
// after
EXPIRY_TIMER = TimerSpec('expiry', on_timer=process_expiry) Defensive patterns
Strategy: validation
Validate before calling
from apache_beam.transforms.userstate import get_dofn_specs
for t in get_dofn_specs(MyDoFn)[1]:
assert t._attached_callback, f'TimerSpec {t.name} has no on_timer callback' Try / catch
try:
validate_stateful_dofn(MyDoFn)
except ValueError as e:
if 'TimerSpec without an associated on_timer' in str(e):
attach_timer_callbacks(MyDoFn)
else:
raise Prevention
- Always pass on_timer=MyDoFn.method when creating a TimerSpec.
- Watch for typos between the timer name and callback method name.
- Add a unit test calling validate_stateful_dofn on every stateful DoFn.
When it happens
Trigger: Declaring TimerSpec('name') without on_timer=, or passing a name instead of the method object so the decorator never attaches a callback; validate_stateful_dofn then finds timer_spec._attached_callback falsy.
Common situations: Typo in the callback parameter name; writing the timer spec before defining the on_timer method; porting code where on_timer was accidentally dropped; using a lambda the mechanism doesn't accept.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- DoFn %r has multiple TimerSpecs with the same name
- The on_timer callback for
- An unsupported sink was specified
- At least one of --render_port or --render_output must be…
- buffer_sec must be >= 0, got
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/fa20d44aaca4fde4.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/transforms/userstate.py:313
"""Validates the proper specification of a stateful DoFn."""
# Get state and timer specs.
all_state_specs, all_timer_specs = get_dofn_specs(dofn)
# Reject DoFns that have multiple state or timer specs with the same name.
if len(all_state_specs) != len(set(s.name for s in all_state_specs)):
raise ValueError(
'DoFn %r has multiple StateSpecs with the same name: %s.' %
(dofn, all_state_specs))
if len(all_timer_specs) != len(set(s.name for s in all_timer_specs)):
raise ValueError(
'DoFn %r has multiple TimerSpecs with the same name: %s.' %
(dofn, all_timer_specs))
# Reject DoFns that use timer specs without corresponding timer callbacks.
for timer_spec in all_timer_specs:
if not timer_spec._attached_callback:
raise ValueError((
'DoFn %r has a TimerSpec without an associated on_timer '
'callback: %s.') % (dofn, timer_spec))
method_name = timer_spec._attached_callback.__name__
if (timer_spec._attached_callback != getattr(dofn, method_name,
None).__func__): # type: ignore[union-attr]
raise ValueError((
'The on_timer callback for %s is not the specified .%s method '
'for DoFn %r (perhaps it was overwritten?).') %
(timer_spec, method_name, dofn))
class BaseTimer(object):
def clear(self, dynamic_timer_tag: str = '') -> None:
raise NotImplementedError
def set(self, timestamp: Timestamp, dynamic_timer_tag: str = '') -> None:
raise NotImplementedError
View on GitHub (pinned to 12126d8942)