apache/beam · error · NotImplementedError

NotImplementedError

Error message

NotImplementedError

What it means

UnboundedReader.start() in apache_beam/io/unbounded_source.py is an abstract interface method that must be implemented by any subclass providing a streaming reader. It positions the reader at the first record and returns whether one is available. Python raises NotImplementedError because the concrete reader class inherits the stub instead of overriding it.

Source

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

    raised here is logged. On bundle retry an uncommitted mark may be re-cut
    over an overlapping span, so this method must be idempotent (acknowledge by
    absolute position).
    """
    pass


class UnboundedReader(object):
  """Reads records from an :class:`UnboundedSource`.

  Lifecycle: exactly one :meth:`start`, then any number of :meth:`advance`
  calls; whenever one returns ``True`` the current record is available via
  :meth:`get_current` / :meth:`get_current_timestamp`. A ``False`` return means
  "no data available right now", which is distinct from end-of-stream: a reader
  signals a permanent end by reporting a watermark of ``MAX_TIMESTAMP``.
  """
  def start(self) -> bool:
    """Positions at the first record; returns whether one is available."""
    raise NotImplementedError

  def advance(self) -> bool:
    """Advances to the next record. ``False`` means no data is available now.

    Should not block. The wrapper enforces the per-bundle record and time caps
    only between records, so a blocking ``start``/``advance`` can overrun the
    time cap and stall the bundle. Return ``False`` when no data is currently
    available instead of waiting.
    """
    raise NotImplementedError

  def get_current(self) -> Any:
    """Returns the record claimed by the last successful start/advance."""
    raise NotImplementedError

  def get_current_timestamp(self) -> Timestamp:
    """Returns the event-time timestamp of the current record."""
    raise NotImplementedError

View on GitHub (pinned to 12126d8942)

Solutions

  1. Implement start() in your UnboundedReader subclass to position at the first record and return True/False.
  2. Verify the method name and signature exactly match `def start(self) -> bool` (watch for typos or wrong casing).
  3. If you only need a bounded source, use a BoundedSource instead of the unbounded interface so the stub is never invoked.

Example fix

// before
class MyReader(UnboundedReader):
  def advance(self) -> bool:
    ...

// after
class MyReader(UnboundedReader):
  def start(self) -> bool:
    self._it = iter(self._source.records)
    return self.advance()
  def advance(self) -> bool:
    ...
Defensive patterns

Strategy: validation

Validate before calling

from apache_beam.io.unbounded_source import UnboundedReader
assert not getattr(reader.start, '__isabstractmethod__', False), 'UnboundedReader.start not implemented'

Type guard

import inspect
def reader_fully_implemented(cls) -> bool:
    stubs = ['start', 'advance', 'get_current', 'get_current_timestamp', 'get_watermark', 'get_checkpoint_mark']
    return all(not getattr(getattr(cls, m, None), '__isabstractmethod__', True) for m in stubs)

Try / catch

try:
  available = reader.start()
except NotImplementedError:
  logger.error('%s does not implement UnboundedReader.start', type(reader).__name__)
  raise

Prevention

When it happens

Trigger: Subclassing UnboundedReader (or a wrapper instantiating it) without implementing start(); the Beam pipeline calls start() when beginning a bundle and hits the stub body.

Common situations: Users building custom streaming sources for runners with the new unbounded-source API; partially migrated implementations where only advance()/get_watermark() were overridden; typos in the override name (e.g. 'starts') leaving the stub in place.

Understand the failure class

Background: "NotImplementedError: Subclasses should override this method" / "must be implemented" — abstract method errors explained — this error's family across 40 libraries.

Related errors


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