RustPython/RustPython · error · ValueError
raw stream already detached
Error message
raw stream already detached
What it means
Raised by _pyio.BufferedIOBase.detach (Lib/_pyio.py:823) when detach() is called on a buffered wrapper whose underlying raw stream was already removed. detach() extracts the raw stream and sets _raw = None; every subsequent detach() on the same wrapper raises ValueError('raw stream already detached'). After detaching, the wrapper is permanently unusable and only the returned raw object remains valid.
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 aaeab4f754)
Solutions
- Call detach() exactly once and keep the returned raw object; drop the dead wrapper reference
- If you need to replace a standard stream, assign a whole new wrapper to sys.stdout instead of detaching the old one
- Guard the call: only detach when buf.raw is not None
- Record detach state (e.g. set a flag) when helpers may detach indirectly
Example fix
// before raw1 = buf.detach() # ... later ... raw2 = buf.detach() # ValueError: raw stream already detached // after raw1 = buf.detach() # operate on raw1 from now on; buf is spent — do not touch it again
Defensive patterns
Strategy: validation
Validate before calling
if buf.raw is not None:
raw = buf.detach() Type guard
def is_detached(buf) -> bool:
return buf.raw is None Try / catch
try:
raw = buf.detach()
except ValueError as e:
if "raw stream already detached" in str(e):
raw = None # was already detached earlier
else:
raise Prevention
- Call detach() exactly once and keep the returned raw object
- After detaching, operate on the raw object — treat the wrapper as dead
- When swapping sys.stdout, assign a new wrapper rather than detaching the old one
When it happens
Trigger: Calling b.detach() twice on the same BufferedReader/Writer/Random; calling detach() after code that already detached (e.g. a helper that unwraps streams); reconfiguration routines that detach sys.stdout's TextIOWrapper and then run again.
Common situations: Swapping sys.stdout/sys.stderr by detaching the existing wrapper; generic 'unwrap the raw stream' utilities invoked multiple times in tests; mixing TextIOWrapper.detach() with atexit reconfiguration.
Related errors
- seek() returned an invalid position
- tell() returned an invalid position
- invalid file: %r
- flush on closed file
- cannot pickle {self.__class__.__name__!r} object
AI-assisted analysis of RustPython/RustPython@aaeab4f754 (2026-08-17).
Data as JSON: /api/errors/880d98ff40bd102f.
Report an issue: GitHub.