apache/beam · error · ValueError

Invalid TimestampCombiner

Error message

Invalid TimestampCombiner: %s.

What it means

TimestampCombiner.get_impl() maps each supported TimestampCombiner enum value to a timeutil implementation; an unrecognized value falls through the elif chain and raises ValueError. This means an invalid or foreign TimestampCombiner instance reached the windowing strategy.

Solutions

  1. Use an enum member: TimestampCombiner.OUTPUT_AT_EARLIEST / _LATEST / _EARLIEST_TRANSFORMED
  2. Convert strings explicitly: TimestampCombiner[config_value] or a mapping dict
  3. Check the Beam version supports the chosen combiner (OUTPUT_AT_EARLIEST_TRANSFORMED requires newer releases)

Example fix

// before
beam.WindowInto(FixedWindows(60), timestamp_combiner='earliest')
// after
beam.WindowInto(FixedWindows(60), timestamp_combiner=TimestampCombiner.OUTPUT_AT_EARLIEST)
Defensive patterns

Strategy: validation

Validate before calling

VALID = {TimestampCombiner.OUTPUT_AT_EARLIEST, TimestampCombiner.OUTPUT_AT_LATEST, TimestampCombiner.OUTPUT_AT_EARLIEST_TRANSFORMED}
if timestamp_combiner not in VALID:
    raise ValueError('invalid timestamp_combiner')

Type guard

def is_combiner(v): return isinstance(v, TimestampCombiner)

Prevention

When it happens

Trigger: Passing a non-TimestampCombiner object (string like 'earliest', an int, or None) as the timestamp_combiner in WindowInto's Windowing; or a stale/custom enum member from a different Beam version.

Common situations: Config-driven windowing where the combiner comes from YAML/CLI as a string and is never converted to TimestampCombiner.X; version mismatch where a combiner existed in one Beam release but not another.

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/e6593a7d1edf2859. Report an issue: GitHub.

Appendix: source

Thrown at sdks/python/apache_beam/transforms/window.py:118

  OUTPUT_AT_EARLIEST = beam_runner_api_pb2.OutputTime.EARLIEST_IN_PANE
  OUTPUT_AT_LATEST = beam_runner_api_pb2.OutputTime.LATEST_IN_PANE
  # TODO(robertwb): Add this to the runner API or remove it.
  OUTPUT_AT_EARLIEST_TRANSFORMED = 'OUTPUT_AT_EARLIEST_TRANSFORMED'

  @staticmethod
  def get_impl(
      timestamp_combiner: beam_runner_api_pb2.OutputTime.Enum,
      window_fn: 'WindowFn') -> timeutil.TimestampCombinerImpl:
    if timestamp_combiner == TimestampCombiner.OUTPUT_AT_EOW:
      return timeutil.OutputAtEndOfWindowImpl()
    elif timestamp_combiner == TimestampCombiner.OUTPUT_AT_EARLIEST:
      return timeutil.OutputAtEarliestInputTimestampImpl()
    elif timestamp_combiner == TimestampCombiner.OUTPUT_AT_LATEST:
      return timeutil.OutputAtLatestInputTimestampImpl()
    elif timestamp_combiner == TimestampCombiner.OUTPUT_AT_EARLIEST_TRANSFORMED:
      return timeutil.OutputAtEarliestTransformedInputTimestampImpl(window_fn)
    else:
      raise ValueError('Invalid TimestampCombiner: %s.' % timestamp_combiner)


class WindowFn(urns.RunnerApiFn, metaclass=abc.ABCMeta):
  """An abstract windowing function defining a basic assign and merge."""
  class AssignContext(object):
    """Context passed to WindowFn.assign()."""
    def __init__(
        self,
        timestamp: TimestampTypes,
        element: Optional[Any] = None,
        window: Optional['BoundedWindow'] = None) -> None:
      self.timestamp = Timestamp.of(timestamp)
      self.element = element
      self.window = window

  @abc.abstractmethod
  def assign(self,
             assign_context: 'AssignContext') -> Iterable['BoundedWindow']:

View on GitHub (pinned to 12126d8942)