python/cpython · error · ValueError
truncate on closed file
Error message
truncate on closed file
What it means
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.
Source
Thrown at Lib/_pyio.py:1012
else:
raise ValueError("unsupported whence value")
return self._pos
def tell(self):
if self.closed:
raise ValueError("tell on closed file")
return self._pos
def peek(self, size=0):
if self.closed:
raise ValueError("peek on closed file")
if size < 1:
return self._buffer[self._pos:self._pos + io.DEFAULT_BUFFER_SIZE]
return self._buffer[self._pos:self._pos + size]
def truncate(self, pos=None):
if self.closed:
raise ValueError("truncate on closed file")
with self._lock:
if pos is None:
pos = self._pos
else:
try:
pos_index = pos.__index__
except AttributeError:
raise TypeError(f"{pos!r} is not an integer")
else:
pos = pos_index()
if pos < 0:
raise ValueError("negative truncate position %r" % (pos,))
del self._buffer[pos:]
return pos
def readable(self):
if self.closed:View on GitHub (pinned to bc6749cc3b)
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.
Example fix
# before
with io.BytesIO() as buf:
buf.write(b"hello")
buf.truncate(2) # ValueError: closed
# after
with io.BytesIO() as buf:
buf.write(b"hello")
buf.truncate(2) Defensive patterns
Strategy: validation
Validate before calling
if not buf.closed:
buf.truncate(target_len) Try / catch
try:
buf.truncate(target_len)
except ValueError as e:
if "closed" in str(e):
log.warning("skip truncate: stream already closed")
else:
raise Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- peek on closed file
- negative truncate position %r
- __getstate__ on closed file
- getvalue on closed file
- getbuffer on closed file
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/02e68bfb09804fad.
Report an issue: GitHub.