{"record":{"id":"5e86c875b5755980","repo":"apache/beam","slug":"dofn-timerparam-expected-timerspec-object","errorCode":null,"errorMessage":"DoFn.TimerParam expected TimerSpec object.","messagePattern":"DoFn\\.TimerParam expected TimerSpec object\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/transforms/core.py","lineNumber":486,"sourceCode":"        'RestrictionParam(%s)' % restriction_provider.__class__.__name__)\n\n\nclass _StateDoFnParam(_DoFnParam):\n  \"\"\"State DoFn parameter.\"\"\"\n  def __init__(self, state_spec):\n    # type: (StateSpec) -> None\n    if not isinstance(state_spec, StateSpec):\n      raise ValueError(\"DoFn.StateParam expected StateSpec object.\")\n    self.state_spec = state_spec\n    self.param_id = 'StateParam(%s)' % state_spec.name\n\n\nclass _TimerDoFnParam(_DoFnParam):\n  \"\"\"Timer DoFn parameter.\"\"\"\n  def __init__(self, timer_spec):\n    # type: (TimerSpec) -> None\n    if not isinstance(timer_spec, TimerSpec):\n      raise ValueError(\"DoFn.TimerParam expected TimerSpec object.\")\n    self.timer_spec = timer_spec\n    self.param_id = 'TimerParam(%s)' % timer_spec.name\n\n\nclass _BundleFinalizerParam(_DoFnParam):\n  \"\"\"Bundle Finalization DoFn parameter.\"\"\"\n  def __init__(self):\n    self._callbacks = []\n    self.param_id = \"FinalizeBundle\"\n\n  def register(self, callback):\n    self._callbacks.append(callback)\n\n  # Log errors when calling callback to make sure all callbacks get called\n  # though there are errors. And errors should not fail pipeline.\n  def finalize_bundle(self):\n    for callback in self._callbacks:\n      try:","sourceCodeStart":468,"sourceCodeEnd":504,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/transforms/core.py#L468-L504","documentation":"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.","triggerScenarios":"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.","commonSituations":"Passing the timer name string; mixing up StateParam and TimerParam arguments; hand-rolled timer declarations copied incorrectly from examples.","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."],"exampleFix":"// before\nEXPIRY_TIMER = DoFn.TimerParam('expiry')\n// after\nEXPIRY_TIMER = DoFn.TimerParam(TimerSpec('expiry', TimeDomain.WATERMARK))","handlingStrategy":"type-guard","validationCode":"from apache_beam.transforms.userstate import TimerSpec\nif not isinstance(timer_spec, TimerSpec):\n    raise TypeError('expected TimerSpec instance, got %r' % (timer_spec,))","typeGuard":"from apache_beam.transforms.userstate import TimerSpec\ndef is_timer_spec(x) -> bool:\n    return isinstance(x, TimerSpec)","tryCatchPattern":"try:\n    param = DoFn.TimerParam(spec)\nexcept ValueError as e:\n    if 'TimerSpec' in str(e):\n        spec = TimerSpec(spec, TimeDomain.WATERMARK) if isinstance(spec, str) else None","preventionTips":["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"],"tags":["apache-beam","dofn","timers","type-check"],"backgroundTag":"type-mismatch","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}