{"record":{"id":"4efbb42ea6da279d","repo":"python/cpython","slug":"getbuffer-on-closed-file","errorCode":null,"errorMessage":"getbuffer on closed file","messagePattern":"getbuffer on closed file","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":919,"sourceCode":"        del state['_lock']\n        return state\n\n    def __setstate__(self, state):\n        self.__dict__.update(state)\n        self._lock = Lock()\n\n    def getvalue(self):\n        \"\"\"Return the bytes value (contents) of the buffer\n        \"\"\"\n        if self.closed:\n            raise ValueError(\"getvalue on closed file\")\n        return bytes(self._buffer)\n\n    def getbuffer(self):\n        \"\"\"Return a readable and writable view of the buffer.\n        \"\"\"\n        if self.closed:\n            raise ValueError(\"getbuffer on closed file\")\n        return memoryview(self._buffer)\n\n    def close(self):\n        if self._buffer is not None:\n            self._buffer = bytearray()\n        super().close()\n\n    def read(self, size=-1):\n        if self.closed:\n            raise ValueError(\"read from closed file\")\n        if size is None:\n            size = -1\n        else:\n            try:\n                size_index = size.__index__\n            except AttributeError:\n                raise TypeError(f\"{size!r} is not an integer\")\n            else:","sourceCodeStart":901,"sourceCodeEnd":937,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L901-L937","documentation":"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.","triggerScenarios":"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.","commonSituations":"Zero-copy interop with numpy, struct, or socket.send in image/audio pipelines; refactors that moved close() earlier while getbuffer() calls stayed late.","solutions":["Acquire the buffer before closing: `view = buf.getbuffer()` and finish all accesses before close().","Skip the explicit close() — BytesIO frees its memory on garbage collection.","If you need the data after close, use getvalue() before closing and operate on the bytes instead."],"exampleFix":"# before\nbuf = io.BytesIO(payload)\nprocess(buf)\nbuf.close()\narr = np.frombuffer(buf.getbuffer(), dtype=np.uint8)  # ValueError\n\n# after\nbuf = io.BytesIO(payload)\nprocess(buf)\narr = np.frombuffer(buf.getbuffer(), dtype=np.uint8)  # use first\nbuf.close()  # close last","handlingStrategy":"validation","validationCode":"def buffer_of(buf: io.BytesIO) -> memoryview:\n    if buf.closed:\n        raise ValueError('BytesIO closed; acquire getbuffer() before close')\n    return buf.getbuffer()","typeGuard":"def is_open_bytesio(v) -> bool:\n    return isinstance(v, io.BytesIO) and not v.closed","tryCatchPattern":"try:\n    view = buf.getbuffer()\nexcept ValueError as e:\n    if 'closed file' in str(e):\n        raise ValueError('buffer released by close(); reopen from stored bytes') from e\n    raise","preventionTips":["Acquire the memoryview before any close() and finish using it before closing.","Keep the bytes if you need the data post-close: data = buf.getvalue().","Do not close BytesIO in producer code when consumers still need getbuffer()."],"tags":["io","bytesio","getbuffer","memoryview","lifecycle","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}