apache/beam · error · ValueError
@on_timer decorator expected TimerSpec.
Error message
@on_timer decorator expected TimerSpec.
What it means
The @on_timer decorator requires its first argument to be a TimerSpec instance, because it attaches the decorated method to that spec's _attached_callback slot. Passing anything else (a string name, a StateSpec, None) is rejected with a ValueError at decoration time.
Solutions
- Pass the TimerSpec instance: @on_timer(MY_TIMER_SPEC) where MY_TIMER_SPEC = TimerSpec('my_timer', TimeDomain.WATERMARK)
- Define the TimerSpec at class level first and reference the object, not its name string
- Ensure the spec argument is not a StateSpec or other spec type
Example fix
// before
@on_timer('my_timer')
def expiry(self): ...
// after
TIMER_SPEC = TimerSpec('my_timer', TimeDomain.WATERMARK)
@on_timer(TIMER_SPEC)
def expiry(self): ... Defensive patterns
Strategy: validation
Validate before calling
assert isinstance(TIMER_SPEC, TimerSpec), 'on_timer requires a TimerSpec instance'
Type guard
from apache_beam.transforms.userstate import TimerSpec
def is_timer_spec(x) -> bool:
return isinstance(x, TimerSpec) Try / catch
try:
_ = MyDoFn() # decoration errors surface at class-definition/import time
except ValueError as e:
if 'on_timer' in str(e):
fix_timer_decorator() Prevention
- Reference the TimerSpec object, never its name string, in @on_timer(...)
- Define TimerSpec constants at class level before the decorated methods
- Add an import-time smoke test that instantiates stateful DoFns to catch decorator mistakes early
When it happens
Trigger: Writing @on_timer('my_timer') with the timer's name string instead of the TimerSpec object; passing a StateSpec or custom object; forgetting to define the TimerSpec constant being referenced.
Common situations: Confusing @on_timer with stateful DoFn parameter injection where timers are passed by TimerSpec via @stateful; copy-pasting examples and replacing the spec constant with a name; older Beam examples using string-based timer references.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Multiple on_timer callbacks registered for %r.
- @on_timer decorator expected callable.
- DoFn %r has a TimerSpec without an associated on_timer…
- DoFn %r has multiple TimerSpecs with the same name
- Encountered an Atomic type that is not currently supported…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/c620e70cd9123b3e.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/transforms/userstate.py:233
coders._TimerCoder(key_coder, window_coder)))
def on_timer(timer_spec: TimerSpec) -> Callable[[CallableT], CallableT]:
"""Decorator for timer firing DoFn method.
This decorator allows a user to specify an on_timer processing method
in a stateful DoFn. Sample usage::
class MyDoFn(DoFn):
TIMER_SPEC = TimerSpec('timer', TimeDomain.WATERMARK)
@on_timer(TIMER_SPEC)
def my_timer_expiry_callback(self):
logging.info('Timer expired!')
"""
if not isinstance(timer_spec, TimerSpec):
raise ValueError('@on_timer decorator expected TimerSpec.')
def _inner(method: CallableT) -> CallableT:
if not callable(method):
raise ValueError('@on_timer decorator expected callable.')
if timer_spec._attached_callback:
raise ValueError(
'Multiple on_timer callbacks registered for %r.' % timer_spec)
timer_spec._attached_callback = method
return method
return _inner
def get_dofn_specs(dofn: 'DoFn') -> tuple[set[StateSpec], set[TimerSpec]]:
"""Gets the state and timer specs for a DoFn, if any.
Args:
dofn (apache_beam.transforms.core.DoFn): The DoFn instance to introspect forView on GitHub (pinned to 12126d8942)