python/cpython · error · ValueError
raw stream already detached
Error message
raw stream already detached
What it means
BufferedRaw.detach (Lib/_pyio.py:823) raises ValueError when called on a buffered stream whose underlying raw object has already been detached (self.raw is None). detach() disassociates the raw stream and returns it for independent use; afterwards the buffered wrapper is unusable, and a second detach is rejected.
Source
Thrown at Lib/_pyio.py:823
### Flush and close ###
def flush(self):
if self.closed:
raise ValueError("flush on closed file")
self.raw.flush()
def close(self):
if self.raw is not None and not self.closed:
try:
# may raise BlockingIOError or BrokenPipeError etc
self.flush()
finally:
self.raw.close()
def detach(self):
if self.raw is None:
raise ValueError("raw stream already detached")
self.flush()
raw = self._raw
self._raw = None
return raw
### Inquiries ###
def seekable(self):
return self.raw.seekable()
@property
def raw(self):
return self._raw
@property
def closed(self):
return self.raw.closed
View on GitHub (pinned to bc6749cc3b)
Solutions
- Call detach() exactly once and keep the returned raw object as the single owner; stop using the buffered wrapper afterwards.
- If taking over a wrapper's buffer (e.g. sys.stdout), ensure no other code (print, logging, atexit, context-manager exit) uses or closes the wrapper afterwards.
- Check `buf.raw is not None` (guarded by try/except since raw is a property) or track detachment in your own state before detaching.
Example fix
# before raw = wrapper.detach() raw2 = wrapper.detach() # ValueError: raw stream already detached # after raw = wrapper.detach() del wrapper # wrapper is spent; use raw directly from here on
Defensive patterns
Strategy: validation
Validate before calling
def detach_once(wrapper, state={'detached': False}):
if state['detached']:
raise ValueError('raw stream already detached earlier')
state['detached'] = True
return wrapper.detach() Try / catch
try:
raw = wrapper.detach()
except ValueError as e:
if 'already detached' in str(e):
raw = None # already taken; handle ownership elsewhere
else:
raise Prevention
- Call detach() once and delete the wrapper reference immediately after.
- When taking over sys.stdout/sys.stdin buffers, disable or reconfigure print/logging first so nothing touches the wrapper later.
- Never wrap a stream you intend to detach in a `with` block — exit's close() will act on a spent wrapper.
When it happens
Trigger: Calling buf.detach() twice; calling read()/write()/flush() after detach() (these access self.raw, which is None, and most paths surface the detach error or AttributeError); detaching in cleanup code that runs again on retry.
Common situations: Taking over sys.stdin/sys.stdout buffers via sys.stdout.detach() or io.TextIOWrapper.detach() and then library code also touching or detaching the stream; mixing manual detach with `with` blocks that close the wrapper on exit.
Related errors
- I/O operation on closed file.
- flush on closed file
- __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/4b8112434d1fa573.
Report an issue: GitHub.