apache/beam · error · ValueError

Positions must be claimed in order: claim

Error message

Positions must be claimed in order: claim '%s' attempted after claim '%s'

What it means

OffsetRangeTracker (restrictions-based) try_claim() enforces claim ordering. It raises ValueError when a position is claimed that is strictly less than the last claimed position, violating the requirement that positions are claimed in monotonically increasing order.

Solutions

  1. Ensure the process loop iterates positions in strictly increasing order and never rewinds.
  2. After a retriable failure, restart processing from restriction_tracker.current_restriction().start with a fresh tracker rather than re-claiming older positions on the same tracker.
  3. Review try_split/primary-and-residual logic so the primary restriction (which keeps claiming) starts where the residual begins, never before the last claim.

Example fix

// before
pos = start
while try_claim(pos):
  process(pos)
  if error: pos = start  # rewinds
  pos += 1
// after
pos = start
while try_claim(pos):
  try:
    process(pos)
  except RetryableError:
    raise  # let runner restart with fresh restriction
  pos += 1
Defensive patterns

Strategy: validation

Validate before calling

if tracker._last_claim is not tracker.UNSTARTED and position < tracker._last_claim:
  raise ValueError('position must not go backwards')

Try / catch

try:
  ok = tracker.try_claim(position)
except ValueError:
  logging.error('claim order violated; restarting from restriction start')

Prevention

When it happens

Trigger: Calling try_claim(position) with position < self._last_claim after a prior successful claim, e.g. a DoFn process loop that rewinds its cursor, or a split/resume path that restarts from an earlier position on the same tracker instance.

Common situations: Custom restriction providers (RestrictionTracker) where the process function re-processes elements after a retriable failure without creating a fresh tracker; incorrectly implemented try_split producing overlapping claims.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at sdks/python/apache_beam/io/range_trackers.py:246

  UNSTARTED = object()

  def __init__(self, start_position=None, stop_position=None):
    self._start_position = start_position
    self._stop_position = stop_position
    self._lock = threading.Lock()
    self._last_claim = self.UNSTARTED

  def start_position(self):
    return self._start_position

  def stop_position(self):
    with self._lock:
      return self._stop_position

  def try_claim(self, position):
    with self._lock:
      if self._last_claim is not self.UNSTARTED and position < self._last_claim:
        raise ValueError(
            "Positions must be claimed in order: "
            "claim '%s' attempted after claim '%s'" %
            (position, self._last_claim))
      elif self._start_position is not None and position < self._start_position:
        raise ValueError(
            "Claim '%s' is before start '%s'" %
            (position, self._start_position))
      if self._stop_position is None or position < self._stop_position:
        self._last_claim = position
        return True
      else:
        return False

  def position_at_fraction(self, fraction):
    return self.fraction_to_position(
        fraction, self._start_position, self._stop_position)

  def try_split(self, position):

View on GitHub (pinned to 12126d8942)