{"record":{"id":"9f273e26d6ed747a","repo":"apache/beam","slug":"start-offset-must-be-not-be-larger-than-the-stop-offset","errorCode":null,"errorMessage":"Start offset must be not be larger than the stop offset. Received %d and %d respectively.","messagePattern":"Start offset must be not be larger than the stop offset\\. Received (.+?) and (.+?) respectively\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/restriction_trackers.py","lineNumber":29,"sourceCode":"# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n#\n\n\"\"\"`iobase.RestrictionTracker` implementations provided with Apache Beam.\"\"\"\n# pytype: skip-file\n\nfrom apache_beam.io.iobase import RestrictionProgress\nfrom apache_beam.io.iobase import RestrictionTracker\nfrom apache_beam.io.range_trackers import OffsetRangeTracker\n\n\nclass OffsetRange(object):\n  def __init__(self, start, stop):\n    if start > stop:\n      raise ValueError(\n          'Start offset must be not be larger than the stop offset. '\n          'Received %d and %d respectively.' % (start, stop))\n    self.start = start\n    self.stop = stop\n\n  def __eq__(self, other):\n    if not isinstance(other, OffsetRange):\n      return False\n\n    return self.start == other.start and self.stop == other.stop\n\n  def __hash__(self):\n    return hash((type(self), self.start, self.stop))\n\n  def __repr__(self):\n    return 'OffsetRange(start=%s, stop=%s)' % (self.start, self.stop)\n\n  def split(self, desired_num_offsets_per_split, min_num_offsets_per_split=1):","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/restriction_trackers.py#L11-L47","documentation":"OffsetRange.__init__ validates that the start offset does not exceed the stop offset when constructing a bounded range for splittable DoFn sources. Apache Beam throws this ValueError immediately at construction because a reversed range is meaningless: it would represent a negative amount of work and break offset-based splitting and progress tracking.","triggerScenarios":"Calling OffsetRange(start, stop) with start > stop, e.g. OffsetRange(100, 0) or computing offsets from user data where a slice end is smaller than the slice beginning.","commonSituations":"Reading byte/row ranges computed from file sizes or user-specified windows where the end was calculated as start + length with a negative length, or swapping argument order.","solutions":["Check the values passed to OffsetRange and ensure stop >= start","Swap the arguments if they were passed in the wrong order","Clamp or validate computed lengths before constructing (e.g. guard length >= 0)","If the range is genuinely empty, pass start == stop, which is allowed"],"exampleFix":"// before\nrange = OffsetRange(end_offset, start_offset)\n// after\nassert start_offset <= end_offset\nrange = OffsetRange(start_offset, end_offset)","handlingStrategy":"validation","validationCode":"def safe_offset_range(start, stop):\n    if start > stop:\n        raise ValueError(f'invalid range: start={start} > stop={stop}')\n    return OffsetRange(start, stop)","typeGuard":null,"tryCatchPattern":"try:\n    rng = OffsetRange(start, stop)\nexcept ValueError as e:\n    logger.error('Invalid OffsetRange: %s', e)\n    rng = None","preventionTips":["Always assert start <= stop before constructing OffsetRange","Derive stop from start + non-negative length only","Add unit tests for boundary cases (start == stop)"],"tags":["apache-beam","python","range-validation"],"backgroundTag":"argument-out-of-range","analyzedSha":"12126d8942aaf848030c478b4c6a28c6af861c66","analyzedAt":"2026-09-13T01:50:10.254Z","contentChangedAt":"2026-09-13T01:50:10.254Z","schemaVersion":2},"datasetVersion":"2026-09-20T03:17:13.778Z"}