apache/beam · error · ValueError
DoFn.TimerParam expected TimerSpec object.
Error message
DoFn.TimerParam expected TimerSpec object.
What it means
ValueError raised by `_TimerDoFnParam.__init__` (exposed as `DoFn.TimerParam`) when the `timer_spec` argument is not an instance of `TimerSpec`. Timers must be declared via `TimerSpec` (or `ClearableTimerSpec`) objects.
Solutions
- Pass a `TimerSpec` instance, e.g. `DoFn.TimerParam(TimerSpec('expiry', TimeDomain.WATERMARK))`.
- Confirm the argument isn't a plain string — the spec holds the name.
- Use `on_timer` callback decorated with `@arrow`-compatible signature matching the spec.
Example fix
// before
EXPIRY_TIMER = DoFn.TimerParam('expiry')
// after
EXPIRY_TIMER = DoFn.TimerParam(TimerSpec('expiry', TimeDomain.WATERMARK)) Defensive patterns
Strategy: type-guard
Validate before calling
from apache_beam.transforms.userstate import TimerSpec
if not isinstance(timer_spec, TimerSpec):
raise TypeError('expected TimerSpec instance, got %r' % (timer_spec,)) Type guard
from apache_beam.transforms.userstate import TimerSpec
def is_timer_spec(x) -> bool:
return isinstance(x, TimerSpec) Try / catch
try:
param = DoFn.TimerParam(spec)
except ValueError as e:
if 'TimerSpec' in str(e):
spec = TimerSpec(spec, TimeDomain.WATERMARK) if isinstance(spec, str) else None Prevention
- Declare timers with TimerSpec(name, TimeDomain.WATERMARK or PROCESSING_TIME)
- Never pass timer name strings to TimerParam
- Keep TimerParam and StateParam arguments separate in DoFn boilerplate
When it happens
Trigger: Writing `DoFn.TimerParam('my_timer')` or passing a state spec / string name instead of a `TimerSpec` instance when declaring a timer parameter in a DoFn.
Common situations: Passing the timer name string; mixing up StateParam and TimerParam arguments; hand-rolled timer declarations copied incorrectly from examples.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Cannot access fire timestamp outside of @OnTimer method.
- Cannot access timer in non-window observing context.
- Cannot access timerFamily in non-window observing context.
- Cannot access timerId as parameter outside of @OnTimer…
- Cannot access timerId as parameter outside of @OnTimer…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/5e86c875b5755980.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/transforms/core.py:486
'RestrictionParam(%s)' % restriction_provider.__class__.__name__)
class _StateDoFnParam(_DoFnParam):
"""State DoFn parameter."""
def __init__(self, state_spec):
# type: (StateSpec) -> None
if not isinstance(state_spec, StateSpec):
raise ValueError("DoFn.StateParam expected StateSpec object.")
self.state_spec = state_spec
self.param_id = 'StateParam(%s)' % state_spec.name
class _TimerDoFnParam(_DoFnParam):
"""Timer DoFn parameter."""
def __init__(self, timer_spec):
# type: (TimerSpec) -> None
if not isinstance(timer_spec, TimerSpec):
raise ValueError("DoFn.TimerParam expected TimerSpec object.")
self.timer_spec = timer_spec
self.param_id = 'TimerParam(%s)' % timer_spec.name
class _BundleFinalizerParam(_DoFnParam):
"""Bundle Finalization DoFn parameter."""
def __init__(self):
self._callbacks = []
self.param_id = "FinalizeBundle"
def register(self, callback):
self._callbacks.append(callback)
# Log errors when calling callback to make sure all callbacks get called
# though there are errors. And errors should not fail pipeline.
def finalize_bundle(self):
for callback in self._callbacks:
try:View on GitHub (pinned to 12126d8942)