apache/beam · error · ValueError
End offset must not be 'None'
Error message
End offset must not be 'None'
What it means
OffsetRangeTracker requires an explicit end offset; None is not a representable position (unbounded end is expressed via the OFFSET_INFINITY sentinel, float('inf')). The constructor raises ValueError when end is None so range tracking and split logic never encounter an undefined position.
Source
Thrown at sdks/python/apache_beam/io/range_trackers.py:56
class OffsetRangeTracker(iobase.RangeTracker):
"""A 'RangeTracker' for non-negative positions of type 'long'."""
# Offset corresponding to infinity. This can only be used as the upper-bound
# of a range, and indicates reading all of the records until the end without
# specifying exactly what the end is.
# Infinite ranges cannot be split because it is impossible to estimate
# progress within them.
OFFSET_INFINITY = float('inf')
def __init__(self, start, end):
super().__init__()
if start is None:
raise ValueError('Start offset must not be \'None\'')
if end is None:
raise ValueError('End offset must not be \'None\'')
assert isinstance(start, int)
if end != self.OFFSET_INFINITY:
assert isinstance(end, int)
assert start <= end
self._start_offset = start
self._stop_offset = end
self._last_record_start = -1
self._last_attempted_record_start = -1
self._offset_of_last_split_point = -1
self._lock = threading.Lock()
self._split_points_seen = 0
self._split_points_unclaimed_callback = None
def start_position(self):View on GitHub (pinned to 12126d8942)
Solutions
- Pass OFFSET_INFINITY for an unbounded end: OffsetRangeTracker(start, OffsetRangeTracker.OFFSET_INFINITY).
- Pass a concrete integer end offset.
- Fix upstream computation of end so it never returns None; validate before constructing.
Example fix
// before OffsetRangeTracker(start, None) // after OffsetRangeTracker(start, OffsetRangeTracker.OFFSET_INFINITY)
Defensive patterns
Strategy: type-guard
Validate before calling
assert end_offset is not None, "end offset required"
if end_offset is None:
end_offset = OffsetRangeTracker.OFFSET_INFINITY Type guard
def is_valid_end(x) -> bool:
return x == float('inf') or (isinstance(x, int) and not isinstance(x, bool)) Try / catch
try:
tracker = OffsetRangeTracker(start, end)
except ValueError as e:
logger.error("Bad offset range: %s", e)
tracker = OffsetRangeTracker(start, OffsetRangeTracker.OFFSET_INFINITY) Prevention
- Use OFFSET_INFINITY (float('inf')) for unbounded ends, never None.
- Validate computed end offsets (e.g. file sizes) before constructing.
- Keep source range computation free of silent None returns.
When it happens
Trigger: OffsetRangeTracker(start, None) — constructing the tracker without an end. Use OffsetRangeTracker.OFFSET_INFINITY for unbounded ranges.
Common situations: Custom bounded/unbounded source implementations passing None instead of the infinity sentinel; computing end from file size that failed to resolve.
Related errors
- Start offset must not be 'None'
- File object must not be None
- Unable to claim position: %s
- Encountered an Atomic type that is not currently supported b
- The first record [starting at %d] must be at a split point
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/bdfd51a07c36d9b3.
Report an issue: GitHub.