{"record":{"id":"e1a237ac4b7dfe28","repo":"RustPython/RustPython","slug":"file-or-stream-is-not-readable","errorCode":null,"errorMessage":"File or stream is not readable.","messagePattern":"File or stream is not readable\\.","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":448,"sourceCode":"    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.\n\n        If False, write() and truncate() will raise OSError.\n        \"\"\"\n        return False\n\n    def _checkWritable(self, msg=None):\n        \"\"\"Internal: raise UnsupportedOperation if file is not writable\n        \"\"\"\n        if not self.writable():\n            raise UnsupportedOperation(\"File or stream is not writable.\"\n                                       if msg is None else msg)\n\n    @property\n    def closed(self):","sourceCodeStart":430,"sourceCodeEnd":466,"githubUrl":"https://github.com/RustPython/RustPython/blob/aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd/Lib/_pyio.py#L430-L466","documentation":"io.UnsupportedOperation raised via IOBase._checkReadable when a read-family call (read, readline, readlines, peek, read1, readinto) hits a stream whose readable() is False - typically a file opened write-only ('w', 'a', 'x', 'wb', ...). The check runs before any syscall; note the write-only file is still created/truncated by open() itself, only the read is refused.","triggerScenarios":"open(path, 'w').read(); f = open(path, 'wb') followed by f.read(4) to 'verify' what was just written; copy-pasted read code inside a writer function; mode passed in from config as 'w' while the code assumes 'r+'.","commonSituations":"Write-then-verify patterns that should re-open in read mode; mixed read/write code where the mode was meant to be 'r+'/'w+'; test harnesses reusing a single open() for both directions.","solutions":["Open with a read-capable mode: 'r' to read, 'r+'/'w+' for both directions","For verification, close and re-open the file in 'rb' after writing","Guard reads with if f.readable(): ..."],"exampleFix":"# before\nf = open(path, 'w')\nf.write(data)\nhead = f.read(16)            # UnsupportedOperation\n\n# after\nwith open(path, 'w') as f:\n    f.write(data)\nwith open(path, 'rb') as f:\n    head = f.read(16)","handlingStrategy":"validation","validationCode":"if f.readable():\n    head = f.read(16)\nelse:\n    raise RuntimeError(f'{f!r} not opened for reading')","typeGuard":"def is_readable(f) -> bool:\n    return bool(getattr(f, 'readable', lambda: False)())","tryCatchPattern":"import io\ntry:\n    head = f.read(16)\nexcept io.UnsupportedOperation:\n    head = None                           # write-only stream; skip verify step","preventionTips":["Choose 'r'/'r+'/'w+' at open time based on which directions the code actually uses","Re-open in read mode to verify written output instead of reading the write handle","Check f.readable() when handling caller-supplied streams"],"tags":["io","read","unsupported-operation","file-mode","stream-capability"],"backgroundTag":"stream-not-readable","analyzedSha":"aaeab4f754b4f40efc0c8ab39cf7c4a3c35a8cfd","analyzedAt":"2026-08-17T00:37:52.100Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}