apache/beam · error · ValueError

key value is out of range

Error message

key value %d is out of range

What it means

Timers in the worker are indexed by a timestamp in microseconds, and this map-like structure enforces a valid timestamp range (RANGE_MIN..RANGE_MAX, derived from the 8-byte key encoding). A TimerMap.add() with a timestamp micros value outside that range raises ValueError. It guards against timestamps that cannot round-trip through the backing store.

Solutions

  1. Clamp the timer timestamp to the valid range before setting (e.g. cap at a safe max like 2262-04-11)
  2. Use a realistic event-time timestamp instead of datetime.max/min sentinels
  3. Adjust window/trigger logic so timers fire within representable range
  4. Add a validation step that rejects out-of-range event times upstream

Example fix

// before
TimerSpec.set_timer(w, 'cleanup', firing_time=datetime.max)
// after
max_ts = datetime.datetime(2262, 4, 11)
TimerSpec.set_timer(w, 'cleanup', firing_time=min(firing_time, max_ts))
Defensive patterns

Strategy: validation

Validate before calling

import apache_beam.utils.timestamp as ts
RANGE_MIN, RANGE_MAX = -9223372036854, 9223372036854  # per worker TimerMap bounds
def timer_ts_ok(dt):
    micros = ts.Timestamp.from_rfc3339(dt.isoformat()).micros if hasattr(dt, 'isoformat') else int(dt) * 1_000_000
    return RANGE_MIN <= micros < RANGE_MAX
# call before set_timer; clamp firing_time otherwise

Try / catch

try:
    ctx.set_timer('cleanup', firing_time)
except ValueError as e:
    if 'key value' in str(e) and 'out of range' in str(e):
        logging.warning('Timer timestamp %s out of range; clamping', firing_time)
        ctx.set_timer('cleanup', min(max(firing_time, min_ts), max_ts))
    else:
        raise

Prevention

When it happens

Trigger: Calling add() on the timer state map with a Timestamp whose .micros exceeds RANGE_MAX or is below RANGE_MIN — e.g. timer set at an extreme timestamp (far past/far future) like 9999-12-31 or negative epoch values.

Common situations: Setting timers at datetime.max/min sentinels; using windows with enormous allowed timestamps; negative timestamps from bad event-time parsing.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/runners/worker/bundle_processor.py:780

      self,
      state_handler: sdk_worker.CachingStateHandler,
      state_key: beam_fn_api_pb2.StateKey,
      value_coder: coders.Coder) -> None:
    self._state_handler = state_handler
    self._state_key = state_key
    self._elem_coder = beam.coders.TupleCoder(
        [coders.VarIntCoder(), coders.coders.LengthPrefixCoder(value_coder)])
    self._cleared = False
    self._pending_adds = SortedDict()
    self._pending_removes = RangeSet()

  def add(self, elem: tuple[timestamp.Timestamp, Any]) -> None:
    assert len(elem) == 2
    key_ts, value = elem
    key = key_ts.micros

    if key >= self.RANGE_MAX or key < self.RANGE_MIN:
      raise ValueError("key value %d is out of range" % key)
    self._pending_adds.setdefault(key, []).append(value)

  def read(self) -> Iterable[tuple[timestamp.Timestamp, Any]]:
    return self.read_range(self.TIMESTAMP_RANGE_MIN, self.TIMESTAMP_RANGE_MAX)

  def read_range(
      self,
      min_timestamp: timestamp.Timestamp,
      limit_timestamp: timestamp.Timestamp
  ) -> Iterable[tuple[timestamp.Timestamp, Any]]:
    # convert timestamp to int, as sort keys are stored as int internally.
    min_key = min_timestamp.micros
    limit_key = limit_timestamp.micros

    keys_to_add = self._pending_adds.irange(
        min_key, limit_key, inclusive=(True, False))

    # use list interpretation here to construct the actual list

View on GitHub (pinned to 12126d8942)