{"record":{"id":"5250b1ba24bcba04","repo":"python/cpython","slug":"file-not-open-for-reading","errorCode":null,"errorMessage":"File not open for reading","messagePattern":"File not open for reading","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":1686,"sourceCode":"                    (class_name, self._fd, self.mode, self._closefd))\n        else:\n            return ('<%s name=%r mode=%r closefd=%r>' %\n                    (class_name, name, self.mode, self._closefd))\n\n    @property\n    def _blksize(self):\n        if self._stat_atopen is None:\n            return DEFAULT_BUFFER_SIZE\n\n        blksize = getattr(self._stat_atopen, \"st_blksize\", 0)\n        # WASI sets blsize to 0\n        if not blksize:\n            return DEFAULT_BUFFER_SIZE\n        return blksize\n\n    def _checkReadable(self):\n        if not self._readable:\n            raise UnsupportedOperation('File not open for reading')\n\n    def _checkWritable(self, msg=None):\n        if not self._writable:\n            raise UnsupportedOperation('File not open for writing')\n\n    def read(self, size=None):\n        \"\"\"Read at most size bytes, returned as bytes.\n\n        If size is less than 0, read all bytes in the file making\n        multiple read calls. See ``FileIO.readall``.\n\n        Attempts to make only one system call, retrying only per\n        PEP 475 (EINTR). This means less data may be returned than\n        requested.\n\n        In non-blocking mode, returns None if no data is available.\n        Return an empty bytes object at EOF.\n        \"\"\"","sourceCodeStart":1668,"sourceCodeEnd":1704,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L1668-L1704","documentation":"Raised by FileIO._checkReadable as io.UnsupportedOperation('File not open for reading') when read/readinto/readall is called on a FileIO whose mode never set the _readable flag (modes 'w', 'a', 'x', and their non-'+' variants). The check runs before any syscall, so the file is never actually read.","triggerScenarios":"f = open('out.txt','wb', buffering=0); f.read() — any read-family call on a write-only or append-only FileIO/TextIOWrapper over it.","commonSituations":"Reusing a write-mode handle for a later read step (e.g. write-then-verify code that forgets to reopen or seek with 'r+b'); mode chosen from config as 'ab' while code also tries to read; debugging sessions reading from a log file still open for append.","solutions":["Open read-write with '+' (e.g. 'r+b', 'w+b') when you must read and write the same handle","Reopen the file in read mode for the read phase, or use a fresh handle","Fix the mode in the config/constant that produced the write-only handle"],"exampleFix":"# before\nf = open('data.bin', 'wb')\nf.write(b'x')\nf.seek(0); f.read()        # UnsupportedOperation: File not open for reading\n\n# after\nf = open('data.bin', 'w+b')\nf.write(b'x')\nf.seek(0); data = f.read()","handlingStrategy":"validation","validationCode":"def read_from(f, n=-1):\n    if not f.readable():\n        raise io.UnsupportedOperation('File not open for reading')\n    return f.read(n)","typeGuard":"def is_readable_handle(f):\n    return not f.closed and f.readable()","tryCatchPattern":"try:\n    data = f.read()\nexcept io.UnsupportedOperation as e:\n    if 'reading' in str(e):\n        f.close()\n        with open(f.name, 'rb') as g:  # reopen read-only\n            data = g.read()\n    else:\n        raise","preventionTips":["Call f.readable() before read-family calls on data-driven handles","Open 'r+b' when a single handle must do both directions","Derive modes from an explicit enum in your code, not ad-hoc strings"],"tags":["python","io","file-io","mode","unsupportedoperation"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}