python/cpython · error · ValueError
write to closed file
Error message
write to closed file
What it means
BytesIO.write (Lib/_pyio.py:960) checks the closed flag inside the memoryview context before mutating the buffer and raises ValueError('write to closed file'). After close() the internal bytearray has been swapped for an empty one, so a late write would either fail confusingly or appear to lose data — the check makes the state explicit.
Source
Thrown at Lib/_pyio.py:960
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 = newpos
return b.take_bytes()
def read1(self, size=-1):
"""This is the same as read.
"""
return self.read(size)
def write(self, b):
if isinstance(b, str):
raise TypeError("can't write str to binary stream")
with memoryview(b) as view:
if self.closed:
raise ValueError("write to closed file")
n = view.nbytes # Size of any bytes-like object
if n == 0:
return 0
with self._lock:
pos = self._pos
if pos > len(self._buffer):
# Pad buffer to pos with null bytes.
self._buffer.resize(pos)
self._buffer[pos:pos + n] = view
self._pos += n
return n
def seek(self, pos, whence=0):
if self.closed:
raise ValueError("seek on closed file")
try:View on GitHub (pinned to bc6749cc3b)
Solutions
- Ensure close() runs only after the last write; reorder cleanup to the very end.
- Guard writes on shared streams: `if not buf.closed: buf.write(chunk)`.
- On cancellation/error paths, drain or finalize pending writes before closing the buffer.
Example fix
# before
buf = io.BytesIO()
try:
for chunk in source():
buf.write(chunk)
except ValueError:
buf.close()
buf.write(b'partial') # ValueError: write to closed file
# after
buf = io.BytesIO()
try:
for chunk in source():
buf.write(chunk)
except ValueError:
pass # keep buf open
finally:
result = buf.getvalue()
buf.close() # close once, at the end Defensive patterns
Strategy: validation
Validate before calling
def write_if_open(buf: io.BytesIO, chunk: bytes) -> int:
if buf.closed:
raise ValueError('BytesIO closed; writes must happen before close')
return buf.write(chunk) Type guard
def is_open_bytesio(v) -> bool:
return isinstance(v, io.BytesIO) and not v.closed Try / catch
try:
buf.write(chunk)
except ValueError as e:
if 'closed file' in str(e):
raise RuntimeError('writer ran after buffer close; reorder cleanup') from e
raise Prevention
- Perform all writes before close(); treat close as the final operation.
- In async/cancel paths, finalize pending writes before closing the buffer.
- Omit explicit close() for BytesIO when ownership is murky — GC handles it.
When it happens
Trigger: buf.write(b'...') after buf.close(); writing inside a loop where an earlier iteration's error handler closed the stream; a `with io.BytesIO()` block exited before a deferred/batched write executes.
Common situations: Buffered writers that accumulate output and flush/close on error, with later code still writing; async tasks writing to a shared BytesIO closed by cancellation; generator pipelines where close propagates downstream early.
Related errors
- __getstate__ on closed file
- getvalue on closed file
- getbuffer on closed file
- read from closed file
- seek on closed file
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/48c116aacbb6d2ff.
Report an issue: GitHub.