{"record":{"id":"1b94b4c12164e6da","repo":"apache/beam","slug":"notimplementederror","errorCode":null,"errorMessage":"NotImplementedError","messagePattern":"NotImplementedError","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/range_trackers.py","lineNumber":292,"sourceCode":"\n      if self._last_claim is self.UNSTARTED or self._last_claim < position:\n        fraction = self.position_to_fraction(\n            position, start=self._start_position, end=self._stop_position)\n        self._stop_position = position\n        return position, fraction\n\n  def fraction_consumed(self):\n    if self._last_claim is self.UNSTARTED:\n      return 0\n    else:\n      return self.position_to_fraction(\n          self._last_claim, self._start_position, self._stop_position)\n\n  def fraction_to_position(self, fraction, start, end):\n    \"\"\"\n    Converts a fraction between 0 and 1 to a position between start and end.\n    \"\"\"\n    raise NotImplementedError\n\n  def position_to_fraction(self, position, start, end):\n    \"\"\"Returns the fraction of keys in the range [start, end) that\n    are less than the given key.\n    \"\"\"\n    raise NotImplementedError\n\n\nclass UnsplittableRangeTracker(iobase.RangeTracker):\n  \"\"\"A RangeTracker that always ignores split requests.\n\n  This can be used to make a given\n  :class:`~apache_beam.io.iobase.RangeTracker` object unsplittable by\n  ignoring all calls to :meth:`.try_split()`. All other calls will be delegated\n  to the given :class:`~apache_beam.io.iobase.RangeTracker`.\n  \"\"\"\n  def __init__(self, range_tracker):\n    \"\"\"Initializes UnsplittableRangeTracker.","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/range_trackers.py#L274-L310","documentation":"iobase.RangeTracker's abstract fraction_to_position() has no default implementation; the base class raises NotImplementedError. Concrete RangeTracker implementations must override it to convert a fraction into a position.","triggerScenarios":"Calling position_at_fraction() on a RangeTracker subclass (used by work rebalancing) that inherits from iobase.RangeTracker but does not override fraction_to_position.","commonSituations":"Implementing a custom RangeTracker for a custom source and forgetting to implement fraction_to_position; enabling dynamic work rebalancing, which then invokes it at runtime.","solutions":["Override fraction_to_position(fraction, start, end) in your RangeTracker subclass with a real conversion (e.g. start + fraction*(end-start)).","If the source cannot support fractional splitting, wrap the tracker in UnsplittableRangeTracker so the method is never called.","Prefer implementing a RestrictionTracker for splittable DoFns instead of the legacy RangeTracker API."],"exampleFix":"// before\nclass MyTracker(iobase.RangeTracker):\n  pass  # fraction_to_position not implemented\n// after\nclass MyTracker(iobase.RangeTracker):\n  def fraction_to_position(self, fraction, start, end):\n    return int(start + fraction * (end - start))","handlingStrategy":"fallback","validationCode":"if type(tracker).fraction_to_position is iobase.RangeTracker.fraction_to_position:\n  tracker = UnsplittableRangeTracker(tracker)","typeGuard":"def implements_fraction_to_position(tracker) -> bool:\n  return type(tracker).fraction_to_position is not iobase.RangeTracker.fraction_to_position","tryCatchPattern":"try:\n  pos = tracker.position_at_fraction(f)\nexcept NotImplementedError:\n  pos = None  # tracker does not support fractional positioning","preventionTips":["Override all abstract methods when subclassing RangeTracker","Wrap non-splittable trackers in UnsplittableRangeTracker","Prefer RestrictionTracker for new sources"],"tags":["python","apache-beam","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-14T11:17:12.474Z"}