python/cpython · error · UnsupportedOperation

File or stream is not readable.

Error message

File or stream is not readable.

What it means

Raised by IOBase._checkReadable() as io.UnsupportedOperation when read() (and readlines/peek-style reads) is called on a stream whose readable() returns False — i.e. a stream opened write- or append-only. It is the runtime enforcement of the mode flags the file was opened with.

Source

Thrown at Lib/_pyio.py:448

    def _checkSeekable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not seekable
        """
        if not self.seekable():
            raise UnsupportedOperation("File or stream is not seekable."
                                       if msg is None else msg)

    def readable(self):
        """Return a bool indicating whether object was opened for reading.

        If False, read() will raise OSError.
        """
        return False

    def _checkReadable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not readable
        """
        if not self.readable():
            raise UnsupportedOperation("File or stream is not readable."
                                       if msg is None else msg)

    def writable(self):
        """Return a bool indicating whether object was opened for writing.

        If False, write() and truncate() will raise OSError.
        """
        return False

    def _checkWritable(self, msg=None):
        """Internal: raise UnsupportedOperation if file is not writable
        """
        if not self.writable():
            raise UnsupportedOperation("File or stream is not writable."
                                       if msg is None else msg)

    @property
    def closed(self):

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Open for read/write with 'r+' or 'w+' if you must read and write the same handle (mind buffering: flush between write and read).
  2. Verify writes by reopening: close, then open(path, 'rb') and read back.
  3. Guard with if stream.readable(): before read attempts in generic code.
  4. Check the mode string you computed — write-only modes are 'w', 'a', 'x' (and their 'b' forms).

Example fix

// before
with open('out.txt', 'w') as f:
    f.write(payload)
    f.seek(0)
    check = f.read()        # UnsupportedOperation: not readable

// after
with open('out.txt', 'w') as f:
    f.write(payload)
with open('out.txt', 'r') as f:
    check = f.read()        # reopen for reading
Defensive patterns

Strategy: type-guard

Validate before calling

if stream.readable():
    data = stream.read(n)
else:
    raise ValueError(f'{stream!r} is not open for reading')

Type guard

def is_readable(stream) -> bool:
    probe = getattr(stream, 'readable', None)
    return callable(probe) and probe()

Try / catch

import io

try:
    data = f.read()
except io.UnsupportedOperation:
    # opened 'w'/'a' — reopen for reading if verification was intended
    with open(f.name, 'rb') as rf:
        data = rf.read()

Prevention

When it happens

Trigger: open('out.txt', 'w').read(); reading from the stdin pipe of a subprocess (p.stdin.read()); calling .read() on a GzipFile opened 'wb'; helper functions that 'verify' by reading back what they just wrote to a write-mode handle.

Common situations: Read-after-write verification on the same handle without reopening; passing a write handle to a logging/tee helper that reads; mode computed wrongly (e.g. 'w' instead of 'r+') so an intended read-write workflow gets a write-only stream.

Related errors


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