{"record":{"id":"a29d0deaa771cc55","repo":"python/cpython","slug":"file-or-stream-is-not-seekable","errorCode":null,"errorMessage":"File or stream is not seekable.","messagePattern":"File or stream is not seekable\\.","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":434,"sourceCode":"        # If close() fails, the caller logs the exception with\n        # sys.unraisablehook. close() must be called at the end at __del__().\n        self.close()\n\n    ### Inquiries ###\n\n    def seekable(self):\n        \"\"\"Return a bool indicating whether object supports random access.\n\n        If False, seek(), tell() and truncate() will raise OSError.\n        This method may need to do a test seek().\n        \"\"\"\n        return False\n\n    def _checkSeekable(self, msg=None):\n        \"\"\"Internal: raise UnsupportedOperation if file is not seekable\n        \"\"\"\n        if not self.seekable():\n            raise UnsupportedOperation(\"File or stream is not seekable.\"\n                                       if msg is None else msg)\n\n    def readable(self):\n        \"\"\"Return a bool indicating whether object was opened for reading.\n\n        If False, read() will raise OSError.\n        \"\"\"\n        return False\n\n    def _checkReadable(self, msg=None):\n        \"\"\"Internal: raise UnsupportedOperation if file is not readable\n        \"\"\"\n        if not self.readable():\n            raise UnsupportedOperation(\"File or stream is not readable.\"\n                                       if msg is None else msg)\n\n    def writable(self):\n        \"\"\"Return a bool indicating whether object was opened for writing.","sourceCodeStart":416,"sourceCodeEnd":452,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L416-L452","documentation":"Raised by IOBase._checkSeekable() as io.UnsupportedOperation when seek(), tell(), or truncate() is called on a stream whose seekable() returns False. Non-seekable streams are sequential-only OS channels — pipes, sockets, terminal input — where a position does not exist, so random access is refused.","triggerScenarios":"sys.stdin.seek(0); f.seek(0) where f wraps a pipe (e.g. output of subprocess.Popen(..., stdout=PIPE)); gzip/bz2 modules or fileinput probing the underlying stream; calling .tell() on a socket makefile() object; code that re-reads input by seeking back to position 0.","commonSituations":"Scripts that work on regular files and then get a pipe redirected in (cmd | script) — the seek(0)-to-reread pattern breaks; stdin re-reading in interactive tools; feeding subprocess pipes into parsers that expect random access; HTTP chunked uploads trying to seek a streamed body.","solutions":["Guard with if stream.seekable(): before seek/tell/truncate.","For stdin re-reading, buffer the content first: data = sys.stdin.buffer.read(), then parse from memory (io.BytesIO(data) is seekable).","Restructure one-pass: single-pass parsing instead of seek-back rereads.","Catch io.UnsupportedOperation where stream provenance varies (file vs pipe)."],"exampleFix":"// before\nsys.stdin.seek(0)          # UnsupportedOperation on a pipe\nlines2 = sys.stdin.readlines()\n\n// after\ndata = sys.stdin.buffer.read()      # one full pass\nimport io\nstream = io.BytesIO(data)          # seekable in-memory copy\nlines2 = stream.readlines()","handlingStrategy":"type-guard","validationCode":"if stream.seekable():\n    stream.seek(0)\n    payload = stream.read()\nelse:\n    payload = stream.read()          # single pass; no rewind possible","typeGuard":"def is_seekable(stream) -> bool:\n    probe = getattr(stream, 'seekable', None)\n    return callable(probe) and probe()","tryCatchPattern":"import io\n\ntry:\n    stream.seek(0)\nexcept io.UnsupportedOperation:\n    stream = io.BytesIO(original_bytes)   # fallback: seekable in-memory copy","preventionTips":["Write one-pass parsers; do not rely on seek(0) to re-read stdin/pipes.","Buffer stdin fully (sys.stdin.buffer.read()) when you need random access, then wrap in io.BytesIO.","Test file-handling code with a pipe (cmd | python x.py) to catch seek assumptions early."],"tags":["io","stream","seek","pipe","stdin","unsupported-operation"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}