python/cpython · error · ValueError

getbuffer on closed file

Error message

getbuffer on closed file

What it means

BytesIO.getbuffer (Lib/_pyio.py:919) returns a writable memoryview over the internal buffer for zero-copy access. After close() the buffer is replaced with an empty bytearray, so getbuffer() on a closed stream raises ValueError rather than hand back a view of an orphaned buffer.

Source

Thrown at Lib/_pyio.py:919

        del state['_lock']
        return state

    def __setstate__(self, state):
        self.__dict__.update(state)
        self._lock = Lock()

    def getvalue(self):
        """Return the bytes value (contents) of the buffer
        """
        if self.closed:
            raise ValueError("getvalue on closed file")
        return bytes(self._buffer)

    def getbuffer(self):
        """Return a readable and writable view of the buffer.
        """
        if self.closed:
            raise ValueError("getbuffer on closed file")
        return memoryview(self._buffer)

    def close(self):
        if self._buffer is not None:
            self._buffer = bytearray()
        super().close()

    def read(self, size=-1):
        if self.closed:
            raise ValueError("read from closed file")
        if size is None:
            size = -1
        else:
            try:
                size_index = size.__index__
            except AttributeError:
                raise TypeError(f"{size!r} is not an integer")
            else:

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Acquire the buffer before closing: `view = buf.getbuffer()` and finish all accesses before close().
  2. Skip the explicit close() — BytesIO frees its memory on garbage collection.
  3. If you need the data after close, use getvalue() before closing and operate on the bytes instead.

Example fix

# before
buf = io.BytesIO(payload)
process(buf)
buf.close()
arr = np.frombuffer(buf.getbuffer(), dtype=np.uint8)  # ValueError

# after
buf = io.BytesIO(payload)
process(buf)
arr = np.frombuffer(buf.getbuffer(), dtype=np.uint8)  # use first
buf.close()  # close last
Defensive patterns

Strategy: validation

Validate before calling

def buffer_of(buf: io.BytesIO) -> memoryview:
    if buf.closed:
        raise ValueError('BytesIO closed; acquire getbuffer() before close')
    return buf.getbuffer()

Type guard

def is_open_bytesio(v) -> bool:
    return isinstance(v, io.BytesIO) and not v.closed

Try / catch

try:
    view = buf.getbuffer()
except ValueError as e:
    if 'closed file' in str(e):
        raise ValueError('buffer released by close(); reopen from stored bytes') from e
    raise

Prevention

When it happens

Trigger: buf.getbuffer() after buf.close(); using the memoryview pattern (`with buf.getbuffer() as view:`) on a BytesIO that a prior code path closed; np.frombuffer(buf.getbuffer(), ...) in a pipeline where cleanup already closed the stream.

Common situations: Zero-copy interop with numpy, struct, or socket.send in image/audio pipelines; refactors that moved close() earlier while getbuffer() calls stayed late.

Related errors


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