python/cpython · error · ValueError
read from closed file
Error message
read from closed file
What it means
BytesIO.read (Lib/_pyio.py:929) checks the closed flag before touching the (already-released) internal buffer and raises ValueError('read from closed file'). Because close() empties the bytearray, reading after close could silently return b'' — the guard converts that silent data loss into an explicit error.
Source
Thrown at Lib/_pyio.py:929
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:
size = size_index()
with self._lock:
if size < 0:
size = len(self._buffer)
if len(self._buffer) <= self._pos:
return b""
newpos = min(len(self._buffer), self._pos + size)
b = self._buffer[self._pos : newpos]
self._pos = newposView on GitHub (pinned to bc6749cc3b)
Solutions
- Remove or relocate the close() so it runs after the final read.
- Use `with io.BytesIO(...) as buf:` and keep every read inside the block.
- Guard with `if not buf.closed:` when ownership of the stream is shared across functions.
Example fix
# before buf = io.BytesIO(data) first = buf.read(4) buf.close() rest = buf.read() # ValueError: read from closed file # after buf = io.BytesIO(data) first = buf.read(4) rest = buf.read() # all reads first buf.close() # close last (or omit)
Defensive patterns
Strategy: validation
Validate before calling
def read_if_open(buf: io.BytesIO, n: int = -1) -> bytes:
if buf.closed:
raise ValueError('BytesIO closed; reads must happen before close')
return buf.read(n) Type guard
def is_open_bytesio(v) -> bool:
return isinstance(v, io.BytesIO) and not v.closed Try / catch
try:
chunk = buf.read(n)
except ValueError as e:
if 'closed file' in str(e):
raise RuntimeError('consumer raced with producer close') from e
raise Prevention
- Keep all reads before close(); reorder cleanup to the end of the scope.
- Use a with-block for BytesIO scopes and read inside it.
- In pipelines, give close() to the final consumer only.
When it happens
Trigger: buf.read() / buf.read(n) after buf.close(); calling read() on a BytesIO returned from a `with` block after exit; a consumer reading a stream that a producer's error handler already closed.
Common situations: Response-body assembly where cleanup closes the buffer before the sender reads it; chaining processors where each stage closes its input; helper that closes on EOF while the caller loops once more.
Related errors
- __getstate__ on closed file
- getvalue on closed file
- getbuffer on closed file
- write to closed file
- seek on closed file
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/6136a30f5bf20a7f.
Report an issue: GitHub.