{"record":{"id":"4372fc752c760cdb","repo":"apache/beam","slug":"whence-mode-r-is-invalid","errorCode":null,"errorMessage":"Whence mode %r is invalid.","messagePattern":"Whence mode %r is invalid\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"sdks/python/apache_beam/io/filesystem.py","lineNumber":416,"sourceCode":"    elif whence == os.SEEK_END:\n      # Determine and cache the uncompressed size of the file\n      if not self._uncompressed_size:\n        logger.warning(\n            \"Seeking relative from end of file is requested. \"\n            \"Need to decompress the whole file once to determine \"\n            \"its size. This might take a while...\")\n        uncompress_start_time = time.time()\n        while self.read(self._read_size):\n          pass\n        uncompress_end_time = time.time()\n        logger.warning(\n            \"Full file decompression for seek \"\n            \"from end took %.2f secs\",\n            (uncompress_end_time - uncompress_start_time))\n        self._uncompressed_size = self._uncompressed_position\n      absolute_offset = self._uncompressed_size + offset\n    else:\n      raise ValueError(\"Whence mode %r is invalid.\" % whence)\n\n    # Determine how many bytes needs to be read before we reach\n    # the requested offset. Rewind if we already passed the position.\n    if absolute_offset < self._uncompressed_position:\n      self._rewind()\n    bytes_to_skip = absolute_offset - self._uncompressed_position\n\n    # Read until the desired position is reached or EOF occurs.\n    while bytes_to_skip:\n      data = self.read(min(self._read_size, bytes_to_skip))\n      if not data:\n        break\n      bytes_to_skip -= len(data)\n\n  def tell(self) -> int:\n    \"\"\"Returns current position in uncompressed file.\"\"\"\n    return self._uncompressed_position\n","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/apache/beam/blob/12126d8942aaf848030c478b4c6a28c6af861c66/sdks/python/apache_beam/io/filesystem.py#L398-L434","documentation":"CompressedFile.seek() only supports the three standard whence modes: os.SEEK_SET, os.SEEK_CUR, and os.SEEK_END. Any other whence value falls through all branches and raises ValueError(\"Whence mode %r is invalid.\"). Compressed streams additionally impose ordering constraints on SEEK_END, but the whence value itself must always be one of the three constants.","triggerScenarios":"Calling `compressed_file.seek(offset, whence)` with whence not in {0,1,2} — e.g. a string like seek(0, 'start'), a custom sentinel like seek(0, 10), or a typo'd constant.","commonSituations":"Porting code that used nonstandard whence enums from another library; passing a string whence because the caller confused file-like seek with a custom API; dynamically computing whence and producing a wrong type.","solutions":["Use the standard constants os.SEEK_SET, os.SEEK_CUR, or os.SEEK_END as the whence argument.","Drop the whence argument entirely for the common case: seek(n) defaults to SEEK_SET.","Guard the whence value before calling seek: assert whence in (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END)."],"exampleFix":"// before\nf.seek(0, 'end')  # ValueError: Whence mode 'end' is invalid.\n// after\nimport os\nf.seek(0, os.SEEK_END)","handlingStrategy":"validation","validationCode":"import os\nassert whence in (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END), f'bad whence: {whence!r}'","typeGuard":"def is_valid_whence(whence) -> bool:\n    import os\n    return whence in (os.SEEK_SET, os.SEEK_CUR, os.SEEK_END)","tryCatchPattern":"try:\n    f.seek(offset, whence)\nexcept ValueError as e:\n    if 'Whence mode' in str(e):\n        f.seek(offset)  # fall back to SEEK_SET\n    else:\n        raise","preventionTips":["Always use os.SEEK_* constants, never raw strings or magic ints, for whence.","Omit the whence argument when SEEK_SET is intended.","Add a unit test covering all three whence modes for your file-like wrappers."],"tags":["python","io","seek","invalid-argument"],"backgroundTag":"invalid-enum-value","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"}