apache/beam · error · TypeError
stop_offset must be a number. Received: %r
Error message
stop_offset must be a number. Received: %r
What it means
_FileBasedSource.__init__ requires stop_offset to be an int unless it is the sentinel OffsetRangeTracker.OFFSET_INFINITY, and raises TypeError otherwise. The stop offset bounds the region of the file the source reads, so a non-integer is rejected at construction time.
Solutions
- Pass an integer or the sentinel range_trackers.OffsetRangeTracker.OFFSET_INFINITY to read to end of file
- Convert with int(stop_offset) or use floor division //
- Fix config/JSON parsing so offsets are decoded as ints
Example fix
// before src = _FileBasedSource(path, 0, None) // after from apache_beam.io import range_trackers src = _FileBasedSource(path, 0, range_trackers.OffsetRangeTracker.OFFSET_INFINITY)
Defensive patterns
Strategy: validation
Validate before calling
from apache_beam.io import range_trackers
if stop_offset != range_trackers.OffsetRangeTracker.OFFSET_INFINITY and not isinstance(stop_offset, int):
raise TypeError(f'stop_offset must be int, got {type(stop_offset).__name__}') Type guard
def is_valid_stop(v) -> bool:
from apache_beam.io import range_trackers
return v == range_trackers.OffsetRangeTracker.OFFSET_INFINITY or (isinstance(v, int) and not isinstance(v, bool)) Try / catch
try:
src = _FileBasedSource(path, start, stop)
except TypeError as e:
if 'stop_offset must be a number' in str(e):
src = _FileBasedSource(path, start, int(stop))
else:
raise Prevention
- Use OffsetRangeTracker.OFFSET_INFINITY rather than None to mean 'to end'
- Use // instead of / when computing offsets from file sizes
- Validate offsets at config-load time, not at source construction
When it happens
Trigger: Constructing a _FileBasedSource with stop_offset as a float (e.g. from division), a string from config/JSON, or None instead of int or OFFSET_INFINITY.
Common situations: Reading offsets from deserialized config; computing stop as file_size / 2 (float division); confusing None with OFFSET_INFINITY to mean 'read to end'.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- start_offset must be a number. Received: %r
- start_offset must be smaller than stop_offset. Received
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
- apache_beam.io.gcp.datastore.v1new.datastoreio.Entity…
- apache_beam.io.gcp.datastore.v1new.datastoreio.Key…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/ff70bb206d5d3dd7.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/io/filebasedsource.py:256
return compression_type == CompressionTypes.UNCOMPRESSED
class _SingleFileSource(iobase.BoundedSource):
"""Denotes a source for a specific file type."""
def __init__(
self,
file_based_source,
file_name,
start_offset,
stop_offset,
min_bundle_size=0,
splittable=True):
if not isinstance(start_offset, int):
raise TypeError(
'start_offset must be a number. Received: %r' % start_offset)
if stop_offset != range_trackers.OffsetRangeTracker.OFFSET_INFINITY:
if not isinstance(stop_offset, int):
raise TypeError(
'stop_offset must be a number. Received: %r' % stop_offset)
if start_offset >= stop_offset:
raise ValueError(
'start_offset must be smaller than stop_offset. Received %d and %d '
'for start and stop offsets respectively' %
(start_offset, stop_offset))
self._file_name = file_name
self._is_gcs_file = file_name.startswith('gs://') if file_name else False
self._start_offset = start_offset
self._stop_offset = stop_offset
self._min_bundle_size = min_bundle_size
self._file_based_source = file_based_source
self._splittable = splittable
def split(self, desired_bundle_size, start_offset=None, stop_offset=None):
if start_offset is None:
start_offset = self._start_offsetView on GitHub (pinned to 12126d8942)