python/cpython · error · UnsupportedOperation

File not open for reading

Error message

File not open for reading

What it means

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.

Source

Thrown at Lib/_pyio.py:1686

                    (class_name, self._fd, self.mode, self._closefd))
        else:
            return ('<%s name=%r mode=%r closefd=%r>' %
                    (class_name, name, self.mode, self._closefd))

    @property
    def _blksize(self):
        if self._stat_atopen is None:
            return DEFAULT_BUFFER_SIZE

        blksize = getattr(self._stat_atopen, "st_blksize", 0)
        # WASI sets blsize to 0
        if not blksize:
            return DEFAULT_BUFFER_SIZE
        return blksize

    def _checkReadable(self):
        if not self._readable:
            raise UnsupportedOperation('File not open for reading')

    def _checkWritable(self, msg=None):
        if not self._writable:
            raise UnsupportedOperation('File not open for writing')

    def read(self, size=None):
        """Read at most size bytes, returned as bytes.

        If size is less than 0, read all bytes in the file making
        multiple read calls. See ``FileIO.readall``.

        Attempts to make only one system call, retrying only per
        PEP 475 (EINTR). This means less data may be returned than
        requested.

        In non-blocking mode, returns None if no data is available.
        Return an empty bytes object at EOF.
        """

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Open read-write with '+' (e.g. 'r+b', 'w+b') when you must read and write the same handle
  2. Reopen the file in read mode for the read phase, or use a fresh handle
  3. Fix the mode in the config/constant that produced the write-only handle

Example fix

# before
f = open('data.bin', 'wb')
f.write(b'x')
f.seek(0); f.read()        # UnsupportedOperation: File not open for reading

# after
f = open('data.bin', 'w+b')
f.write(b'x')
f.seek(0); data = f.read()
Defensive patterns

Strategy: validation

Validate before calling

def read_from(f, n=-1):
    if not f.readable():
        raise io.UnsupportedOperation('File not open for reading')
    return f.read(n)

Type guard

def is_readable_handle(f):
    return not f.closed and f.readable()

Try / catch

try:
    data = f.read()
except io.UnsupportedOperation as e:
    if 'reading' in str(e):
        f.close()
        with open(f.name, 'rb') as g:  # reopen read-only
            data = g.read()
    else:
        raise

Prevention

When it happens

Trigger: f = open('out.txt','wb', buffering=0); f.read() — any read-family call on a write-only or append-only FileIO/TextIOWrapper over it.

Common situations: 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.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/5250b1ba24bcba04. Report an issue: GitHub.