apache/beam · error · Exception
get_position_for_fraction_consumed is not applicable for an…
Error message
get_position_for_fraction_consumed is not applicable for an unbounded range
What it means
OffsetRangeTracker.position_at_fraction() computes the position corresponding to a fraction of the consumed range. It raises a plain Exception when the range is unbounded (stop_position() == OFFSET_INFINITY), because a fraction of infinity is undefined.
Solutions
- Only use a bounded range for sources that support fractional splitting: construct OffsetRangeTracker with a finite stop position.
- Implement position_at_fraction in your custom RangeTracker subclass to return a sensible position (e.g. last attempted position) for unbounded ranges.
- Disable dynamic work rebalancing for this source (or wrap it in UnsplittableRangeTracker) so position_at_fraction is never called.
Example fix
// before tracker = beam.io.range_trackers.OffsetRangeTracker(0, OffsetRangeTracker.OFFSET_INFINITY) pos = tracker.position_at_fraction(0.5) // after tracker = beam.io.range_trackers.OffsetRangeTracker(0, 1000) # finite stop pos = tracker.position_at_fraction(0.5)
Defensive patterns
Strategy: validation
Validate before calling
if tracker.stop_position() == OffsetRangeTracker.OFFSET_INFINITY:
raise ValueError('fractional split not supported for unbounded range') Type guard
def supports_fractional_split(tracker) -> bool: return tracker.stop_position() != OffsetRangeTracker.OFFSET_INFINITY
Try / catch
try: pos = tracker.position_at_fraction(0.5) except Exception: pos = tracker.stop_position() # cannot split unbounded range
Prevention
- Use finite stop positions for splittable bounded sources
- Disable dynamic work rebalancing for unbounded sources
- Override position_at_fraction in custom trackers
When it happens
Trigger: Calling position_at_fraction(fraction) (used by dynamic work rebalancing / split_at_fraction) on an OffsetRangeTracker whose stop position is OFFSET_INFINITY, e.g. an unbounded streaming source or a tracker built with stop=None/infinity.
Common situations: Running autoscaling/dynamic work rebalancing against a custom unbounded source; converting an infinite OffsetRangeTracker from streaming code into a splittable-DoFn context that requests fractional splits.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- A schema is required to write non-schema'd data.
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
- An explicit schema is required to write non-schema'd…
- Cannot call read after iterating.
- Cannot create a temporary directory for root path prefix
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/59df8800d73f0f8f.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/range_trackers.py:193
def fraction_consumed(self):
with self._lock:
# self.last_record_start may become larger than self.end_offset when
# reading the records since any record that starts before the first 'split
# point' at or after the defined 'stop offset' is considered to be within
# the range of the OffsetRangeTracker. Hence fraction could be > 1.
# self.last_record_start is initialized to -1, hence fraction may be < 0.
# Bounding the to range [0, 1].
return self.position_to_fraction(
self._last_record_start, self.start_position(), self.stop_position())
def position_to_fraction(self, pos, start, stop):
fraction = 1.0 * (pos - start) / (stop - start) if start != stop else 0.0
return max(0.0, min(1.0, fraction))
def position_at_fraction(self, fraction):
if self.stop_position() == OffsetRangeTracker.OFFSET_INFINITY:
raise Exception(
'get_position_for_fraction_consumed is not applicable for an '
'unbounded range')
return int(
math.ceil(
self.start_position() + fraction *
(self.stop_position() - self.start_position())))
def split_points(self):
with self._lock:
split_points_consumed = (
0 if self._split_points_seen == 0 else self._split_points_seen - 1)
split_points_unclaimed = (
self._split_points_unclaimed_callback(self.stop_position())
if self._split_points_unclaimed_callback else
iobase.RangeTracker.SPLIT_POINTS_UNKNOWN)
split_points_remaining = (
iobase.RangeTracker.SPLIT_POINTS_UNKNOWN if split_points_unclaimed
== iobase.RangeTracker.SPLIT_POINTS_UNKNOWN elseView on GitHub (pinned to 12126d8942)