{"record":{"id":"a387aa0c7ba5ed63","repo":"apache/beam","slug":"notimplementederror-cells","errorCode":null,"errorMessage":"NotImplementedError","messagePattern":"NotImplementedError","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/metrics/cells.py","lineNumber":71,"sourceCode":"_LOGGER = logging.getLogger(__name__)\n\n\nclass MetricCell(object):\n  \"\"\"For internal use only; no backwards-compatibility guarantees.\n\n  Accumulates in-memory changes to a metric.\n\n  A MetricCell represents a specific metric in a single context and bundle.\n  All subclasses must be thread safe, as these are used in the pipeline runners,\n  and may be subject to parallel/concurrent updates. Cells should only be used\n  directly within a runner.\n  \"\"\"\n  def __init__(self):\n    self._lock = threading.Lock()\n    self._start_time = None\n\n  def update(self, value):\n    raise NotImplementedError\n\n  def get_cumulative(self):\n    raise NotImplementedError\n\n  def to_runner_api_monitoring_info(self, name, transform_id):\n    if not self._start_time:\n      self._start_time = datetime.now(timezone.utc)\n    mi = self.to_runner_api_monitoring_info_impl(name, transform_id)\n    mi.start_time.FromDatetime(self._start_time)\n    return mi\n\n  def to_runner_api_monitoring_info_impl(self, name, transform_id):\n    raise NotImplementedError\n\n  def reset(self):\n    # type: () -> None\n    raise NotImplementedError\n","sourceCodeStart":53,"sourceCodeEnd":89,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/metrics/cells.py#L53-L89","documentation":"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.","triggerScenarios":"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.","commonSituations":"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).","solutions":["Use concrete cell types (CounterCell, DistributionCell, GaugeCell) or the user-facing Metric API (metrics.Metrics.counter(...)) instead of instantiating MetricsCell directly","Implement update() in your custom cell subclass","If this appears in runner code, ensure the runner constructs concrete cells, not the base class"],"exampleFix":"// before\nclass MyCell(MetricsCell):\n  def get_cumulative(self): ...\n// after\nclass MyCell(MetricsCell):\n  def update(self, value):\n    with self._lock:\n      self._value += value\n  def get_cumulative(self): ...","handlingStrategy":"type-guard","validationCode":"from apache_beam.metrics import cells\nassert isinstance(cell, (cells.CounterCell, cells.DistributionCell, cells.GaugeCell))","typeGuard":"def is_concrete_cell(c) -> bool:\n    from apache_beam.metrics import cells\n    return type(c) is not cells.MetricsCell and isinstance(c, cells.MetricsCell)","tryCatchPattern":"try:\n    cell.update(value)\nexcept NotImplementedError:\n    raise TypeError('use a concrete MetricsCell subclass, not MetricsCell')","preventionTips":["Instantiate concrete cells (CounterCell, DistributionCell, GaugeCell), never MetricsCell","Prefer the public Metrics API over raw cells","When subclassing MetricsCell, implement update, get_cumulative, to_runner_api_monitoring_info_impl, and reset"],"tags":["python","apache-beam","metrics","abstract-method"],"backgroundTag":"abstract-method-not-implemented","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}