apache/beam · error · ValueError

Unsupported TimeDomain: %r.

Error message

Unsupported TimeDomain: %r.

What it means

TimerSpec.__init__ accepts only TimeDomain.WATERMARK or TimeDomain.REAL_TIME as the time_domain argument. Any other value (arbitrary strings, EVENT_TIME misspellings, processing-time variants) is rejected with a ValueError, since the runner needs a well-defined time domain to schedule the timer.

Solutions

  1. Use TimeDomain.WATERMARK for event-time timers or TimeDomain.REAL_TIME for processing-time timers
  2. Import TimeDomain from apache_beam.transforms.userstate and use the enum members rather than raw strings
  3. Fix misspellings — e.g. 'processing_time' should be TimeDomain.REAL_TIME

Example fix

// before
spec = TimerSpec('my_timer', 'processing_time')
// after
from apache_beam.transforms.userstate import TimeDomain
spec = TimerSpec('my_timer', TimeDomain.REAL_TIME)
Defensive patterns

Strategy: validation

Validate before calling

from apache_beam.transforms.userstate import TimeDomain
assert time_domain in (TimeDomain.WATERMARK, TimeDomain.REAL_TIME), f'bad time_domain: {time_domain!r}'

Type guard

def is_valid_time_domain(td) -> bool:
    return td in (TimeDomain.WATERMARK, TimeDomain.REAL_TIME)

Try / catch

try:
    spec = TimerSpec('t', time_domain)
except ValueError as e:
    raise ValueError(f'fix time_domain, must be TimeDomain.WATERMARK or REAL_TIME: {e}')

Prevention

When it happens

Trigger: TimerSpec('name', 'processing_time') with a wrong string; passing TimeDomain.EVENT_TIME or other enum members not in (WATERMARK, REAL_TIME); passing None or an int instead of a TimeDomain member.

Common situations: Typos like 'processingtime'; copy-pasting from other streaming frameworks that use different time-domain enums; assuming PROCESSING_TIME is a valid name when the Beam Python SDK calls it REAL_TIME.

Understand the failure class

Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/transforms/userstate.py:202

        ('clear_bit', bool),
        ('fire_timestamp', Optional['Timestamp']),
        ('hold_timestamp', Optional['Timestamp']),
        ('paneinfo', Optional['windowed_value.PaneInfo']),
    ])


# TODO(BEAM-9562): Plumb through actual key_coder and window_coder.
class TimerSpec(object):
  """Specification for a user stateful DoFn timer.
     Read more about Timers here:
     https://beam.apache.org/documentation/programming-guide/#timers
  """
  prefix = "ts-"

  def __init__(self, name: str, time_domain: str) -> None:
    self.name = self.prefix + name
    if time_domain not in (TimeDomain.WATERMARK, TimeDomain.REAL_TIME):
      raise ValueError('Unsupported TimeDomain: %r.' % (time_domain, ))
    self.time_domain = time_domain
    self._attached_callback: Optional[Callable] = None

  def __repr__(self) -> str:
    return '%s(%s)' % (self.__class__.__name__, self.name)

  def to_runner_api(
      self, context: 'PipelineContext', key_coder: Coder,
      window_coder: Coder) -> beam_runner_api_pb2.TimerFamilySpec:
    return beam_runner_api_pb2.TimerFamilySpec(
        time_domain=TimeDomain.to_runner_api(self.time_domain),
        timer_family_coder_id=context.coders.get_id(
            coders._TimerCoder(key_coder, window_coder)))


def on_timer(timer_spec: TimerSpec) -> Callable[[CallableT], CallableT]:
  """Decorator for timer firing DoFn method.

View on GitHub (pinned to 12126d8942)