{"record":{"id":"73280d5606dcead1","repo":"python/cpython","slug":"seek-returned-an-invalid-position","errorCode":null,"errorMessage":"seek() returned an invalid position","messagePattern":"seek\\(\\) returned an invalid position","errorType":"exception","errorClass":"OSError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":782,"sourceCode":"\nclass _BufferedIOMixin(BufferedIOBase):\n\n    \"\"\"A mixin implementation of BufferedIOBase with an underlying raw stream.\n\n    This passes most requests on to the underlying raw stream.  It\n    does *not* provide implementations of read(), readinto() or\n    write().\n    \"\"\"\n\n    def __init__(self, raw):\n        self._raw = raw\n\n    ### Positioning ###\n\n    def seek(self, pos, whence=0):\n        new_position = self.raw.seek(pos, whence)\n        if new_position < 0:\n            raise OSError(\"seek() returned an invalid position\")\n        return new_position\n\n    def tell(self):\n        pos = self.raw.tell()\n        if pos < 0:\n            raise OSError(\"tell() returned an invalid position\")\n        return pos\n\n    def truncate(self, pos=None):\n        self._checkClosed()\n        self._checkWritable()\n\n        # Flush the stream.  We're mixing buffered I/O with lower-level I/O,\n        # and a flush may be necessary to synch both views of the current\n        # file state.\n        self.flush()\n\n        if pos is None:","sourceCodeStart":764,"sourceCodeEnd":800,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L764-L800","documentation":"BufferedRaw.seek (Lib/_pyio.py:782) delegates to the underlying raw stream's seek(pos, whence) and validates the result: a seek must return the new absolute position, which can never be negative. If the raw object returns a negative number, the buffered layer raises a plain OSError because the raw stream is broken or misimplemented.","triggerScenarios":"A custom raw stream whose seek() returns -1 on failure (a C-convention errno style) instead of raising; seek() returning the whence-relative offset or an uninitialized variable; wrapping a device or socket-like object in a buffered reader without a real seek.","commonSituations":"Porting C library wrappers that use -1 sentinel returns; mocking raw.seek in tests to return -1; implementing file-like adapters over pipes or sockets where seek is meaningless but implemented anyway.","solutions":["Fix the custom raw seek() to return the new absolute position (a non-negative int) on success.","On failure, raise OSError from the raw seek() instead of returning a sentinel like -1.","If the underlying object is not seekable, return 0-style identity or raise OSError(ESPIPE) from seekable() checks, and have callers honor seekable() before calling seek()."],"exampleFix":"# before\nclass MyRaw(io.RawIOBase):\n    def seek(self, pos, whence=0):\n        if whence != 0:\n            return -1  # -> OSError: seek() returned an invalid position\n        self._off = pos\n        return self._off\n\n# after\nclass MyRaw(io.RawIOBase):\n    def seek(self, pos, whence=0):\n        if whence != 0:\n            raise OSError('unsupported whence')\n        self._off = pos\n        return self._off  # always a non-negative absolute position","handlingStrategy":"validation","validationCode":"if not f.seekable():\n    raise OSError('stream is not seekable')\nnew_pos = f.seek(pos, whence)  # raw layer validates the returned position","typeGuard":null,"tryCatchPattern":"try:\n    f.seek(0)\nexcept OSError as e:\n    if 'invalid position' in str(e):\n        # underlying raw stream is broken; cannot recover transparently\n        raise\n    raise","preventionTips":["Custom raw seek() must return the new absolute position (non-negative int), never -1.","Raise OSError on failure inside the raw layer instead of returning sentinels.","Check seekable() before seeking streams you do not control."],"tags":["io","seek","custom-stream","invariant","oserror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}