apache/beam · error · NotImplementedError

NotImplementedError

Error message

NotImplementedError

What it means

MetricsCell is the abstract base class for all metric cells in apache_beam.metrics.cells. update(value) is the abstract mutation hook; the base class raises NotImplementedError because each concrete metric type (counter, distribution, gauge) updates differently.

Source

Thrown at sdks/python/apache_beam/metrics/cells.py:71

_LOGGER = logging.getLogger(__name__)


class MetricCell(object):
  """For internal use only; no backwards-compatibility guarantees.

  Accumulates in-memory changes to a metric.

  A MetricCell represents a specific metric in a single context and bundle.
  All subclasses must be thread safe, as these are used in the pipeline runners,
  and may be subject to parallel/concurrent updates. Cells should only be used
  directly within a runner.
  """
  def __init__(self):
    self._lock = threading.Lock()
    self._start_time = None

  def update(self, value):
    raise NotImplementedError

  def get_cumulative(self):
    raise NotImplementedError

  def to_runner_api_monitoring_info(self, name, transform_id):
    if not self._start_time:
      self._start_time = datetime.now(timezone.utc)
    mi = self.to_runner_api_monitoring_info_impl(name, transform_id)
    mi.start_time.FromDatetime(self._start_time)
    return mi

  def to_runner_api_monitoring_info_impl(self, name, transform_id):
    raise NotImplementedError

  def reset(self):
    # type: () -> None
    raise NotImplementedError

View on GitHub (pinned to 12126d8942)

Solutions

  1. Use concrete cell types (CounterCell, DistributionCell, GaugeCell) or the user-facing Metric API (metrics.Metrics.counter(...)) instead of instantiating MetricsCell directly
  2. Implement update() in your custom cell subclass
  3. If this appears in runner code, ensure the runner constructs concrete cells, not the base class

Example fix

// before
class MyCell(MetricsCell):
  def get_cumulative(self): ...
// after
class MyCell(MetricsCell):
  def update(self, value):
    with self._lock:
      self._value += value
  def get_cumulative(self): ...
Defensive patterns

Strategy: type-guard

Validate before calling

from apache_beam.metrics import cells
assert isinstance(cell, (cells.CounterCell, cells.DistributionCell, cells.GaugeCell))

Type guard

def is_concrete_cell(c) -> bool:
    from apache_beam.metrics import cells
    return type(c) is not cells.MetricsCell and isinstance(c, cells.MetricsCell)

Try / catch

try:
    cell.update(value)
except NotImplementedError:
    raise TypeError('use a concrete MetricsCell subclass, not MetricsCell')

Prevention

When it happens

Trigger: Calling update() directly on a MetricsCell base instance or on a custom cell subclass that only implements get_cumulative/to_runner_api_monitoring_info_impl but not update.

Common situations: Users writing custom metric cell types for testing or custom runners and forgetting update(); accidentally constructing the abstract base instead of a concrete cell (e.g. CounterCell, DistributionCell).

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/a387aa0c7ba5ed63. Report an issue: GitHub.