{"record":{"id":"02e68bfb09804fad","repo":"python/cpython","slug":"truncate-on-closed-file","errorCode":null,"errorMessage":"truncate on closed file","messagePattern":"truncate on closed file","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pyio.py","lineNumber":1012,"sourceCode":"        else:\n            raise ValueError(\"unsupported whence value\")\n        return self._pos\n\n    def tell(self):\n        if self.closed:\n            raise ValueError(\"tell on closed file\")\n        return self._pos\n\n    def peek(self, size=0):\n        if self.closed:\n            raise ValueError(\"peek on closed file\")\n        if size < 1:\n            return self._buffer[self._pos:self._pos + io.DEFAULT_BUFFER_SIZE]\n        return self._buffer[self._pos:self._pos + size]\n\n    def truncate(self, pos=None):\n        if self.closed:\n            raise ValueError(\"truncate on closed file\")\n\n        with self._lock:\n            if pos is None:\n                pos = self._pos\n            else:\n                try:\n                    pos_index = pos.__index__\n                except AttributeError:\n                    raise TypeError(f\"{pos!r} is not an integer\")\n                else:\n                    pos = pos_index()\n                if pos < 0:\n                    raise ValueError(\"negative truncate position %r\" % (pos,))\n            del self._buffer[pos:]\n        return pos\n\n    def readable(self):\n        if self.closed:","sourceCodeStart":994,"sourceCodeEnd":1030,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyio.py#L994-L1030","documentation":"Raised by BytesIO.truncate() when called on a stream that is already closed. truncate() would otherwise shrink the in-memory buffer to the given position (defaulting to the current position), but the guard 'if self.closed' rejects the operation up front. Like all closed-stream errors in _pyio it is a ValueError.","triggerScenarios":"Calling bio.truncate() or bio.truncate(n) on a BytesIO after bio.close(); commonly hit when truncate is called in a finally/except path after the file was already closed.","commonSituations":"Cleanup handlers that truncate 'to commit what was written' after closing; retry logic that truncates on failure but the stream was closed by a prior error; double-close followed by truncate.","solutions":["Call truncate() before close(), typically right after finishing writes.","Check 'if not bio.closed:' before truncating.","Restructure so the with-block body contains both the writes and the truncate."],"exampleFix":"# before\nwith io.BytesIO() as buf:\n    buf.write(b\"hello\")\nbuf.truncate(2)  # ValueError: closed\n\n# after\nwith io.BytesIO() as buf:\n    buf.write(b\"hello\")\n    buf.truncate(2)","handlingStrategy":"validation","validationCode":"if not buf.closed:\n    buf.truncate(target_len)","typeGuard":null,"tryCatchPattern":"try:\n    buf.truncate(target_len)\nexcept ValueError as e:\n    if \"closed\" in str(e):\n        log.warning(\"skip truncate: stream already closed\")\n    else:\n        raise","preventionTips":["Call truncate while the stream is open, immediately after the last write.","Never truncate in finally/except paths that may run after close().","Store the intended final length up front so cleanup never needs I/O."],"tags":["python","io","bytesio","truncate","closed-file","valueerror"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}