apache/beam · error · ValueError

max_read_time_seconds must be > 0, got %r

Error message

max_read_time_seconds must be > 0, got %r

What it means

max_read_time_seconds caps the wall-clock duration of a single bundle read; it must be strictly positive. The constructor raises ValueError for zero or negative values, which would immediately terminate every bundle and make progress impossible.

Source

Thrown at sdks/python/apache_beam/io/unbounded_source.py:951

      checked between records, so a reader that blocks inside ``advance()`` may
      overrun it; ``max_records_per_bundle`` is the hard backstop.

  The bundle self-checkpoints as soon as either cap is reached.
  """
  def __init__(
      self,
      source: UnboundedSource,
      poll_interval: float = _DEFAULT_POLL_INTERVAL_SECONDS,
      max_records_per_bundle: int = _DEFAULT_MAX_RECORDS_PER_BUNDLE,
      max_read_time_seconds: float = _DEFAULT_MAX_READ_TIME_SECONDS):
    if not isinstance(source, UnboundedSource):
      raise TypeError('source must be an UnboundedSource, got %r' % (source, ))
    if max_records_per_bundle < 1:
      raise ValueError(
          'max_records_per_bundle must be >= 1, got %r' %
          (max_records_per_bundle, ))
    if max_read_time_seconds <= 0:
      raise ValueError(
          'max_read_time_seconds must be > 0, got %r' %
          (max_read_time_seconds, ))
    if poll_interval < 0:
      raise ValueError(
          'poll_interval must be >= 0, got %r' % (poll_interval, ))
    super().__init__()
    self._source = source
    self._poll_interval = poll_interval
    self._max_records_per_bundle = max_records_per_bundle
    self._max_read_time_seconds = max_read_time_seconds

  def expand(self, pbegin):
    source = self._source
    output_coder = source.default_output_coder()
    # The source is the SDF element used to derive the initial restriction.
    # process() reads from the restriction, so it does not use the element
    # directly.
    output = (

View on GitHub (pinned to 12126d8942)

Solutions

  1. Pass a positive float, e.g. max_read_time_seconds=60.0
  2. Validate/clamp upstream: max_read_time_seconds=max(1e-3, value)
  3. For 'no limit' behavior, use a very large value instead of 0

Example fix

# before
reader = Reader(source, max_read_time_seconds=0)
# after
reader = Reader(source, max_read_time_seconds=300.0)
Defensive patterns

Strategy: validation

Validate before calling

if float(max_read_time_seconds) <= 0:
    raise ValueError('max_read_time_seconds must be > 0')

Try / catch

try:
    reader = Reader(source, max_read_time_seconds=t)
except ValueError:
    reader = Reader(source, max_read_time_seconds=60.0)  # safe default

Prevention

When it happens

Trigger: Initializing the reader with max_read_time_seconds=0 or negative, typically from a mistyped config or a computation like (end - start) that evaluated to 0.

Common situations: Setting 0 intending 'no limit' (not valid here); unit tests passing 0 to 'disable' the cap; duration calculations in seconds returning 0 or negative due to clock issues.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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