Textualize/rich · error · UnsupportedOperation
writelines
Error message
writelines
What it means
The _Reader object returned by Progress.wrap_file() is a read-only progress-tracking file wrapper. .writelines() is explicitly stubbed to raise io.UnsupportedOperation('writelines') because the class only supports read operations that advance the progress bar; it is not a writable stream.
Source
Thrown at rich/progress.py:282
def close(self) -> None:
if self.close_handle:
self.handle.close()
self._closed = True
def seek(self, offset: int, whence: int = 0) -> int:
pos = self.handle.seek(offset, whence)
self.progress.update(self.task, completed=pos)
return pos
def tell(self) -> int:
return self.handle.tell()
def write(self, s: Any) -> int:
raise UnsupportedOperation("write")
def writelines(self, lines: Iterable[Any]) -> None:
raise UnsupportedOperation("writelines")
class _ReadContext(ContextManager[_I], Generic[_I]):
"""A utility class to handle a context for both a reader and a progress."""
def __init__(self, progress: "Progress", reader: _I) -> None:
self.progress = progress
self.reader: _I = reader
def __enter__(self) -> _I:
self.progress.start()
return self.reader.__enter__()
def __exit__(
self,
exc_type: Optional[Type[BaseException]],
exc_val: Optional[BaseException],
exc_tb: Optional[TracebackType],View on GitHub (pinned to 9d8f9a372c)
Solutions
- Perform writelines on the underlying raw file object; use the wrapper only for reads.
- For write progress, wrap manually: open the file normally, write, then progress.update(task, completed=f.tell()) after each chunk.
- Verify the direction of your transfer: wrap_file/Progress.open are for reading (downloads); there is no built-in write wrapper in this API.
Example fix
# before
with progress.open('out.txt', 'rb', total=n) as p:
p.writelines(lines) # UnsupportedOperation
# after
with open('out.txt', 'wb') as f:
f.writelines(lines)
progress.update(task, completed=f.tell()) Defensive patterns
Strategy: type-guard
Validate before calling
# writelines only on real writable streams import io assert isinstance(f, io.IOBase) and f.writable(), 'need a writable raw handle'
Type guard
def is_writable_stream(obj: object) -> bool:
return isinstance(obj, io.IOBase) and not isinstance(getattr(obj, 'handle', obj), type(None)) and getattr(obj, 'writable', lambda: False)() Prevention
- Never pass rich _Reader wrappers as the destination of writelines/copyfileobj.
- Write to the raw file object; update the progress bar manually.
When it happens
Trigger: Calling wrapped.writelines(lines) on the return value of Progress.wrap_file(...) or Progress.open(...). Commonly hit when the wrapper is passed to a generic serialization routine (csv.writer(...).writerows on a wrapped handle, json.dump into the wrapper) that calls writelines internally.
Common situations: Using Progress.open() while building an output file with a library that writes via writelines; confusing the download-progress wrapper for a read/write stream; copying code that used open() directly into a Progress.open() context.
Related errors
- write
- invalid mode {mode!r}
- unable to get the total number of bytes, please specify 'tot
- can't have unbuffered text I/O
- slices with step!=1 are not supported
AI-assisted analysis of Textualize/rich@9d8f9a372c (2026-08-15).
Data as JSON: /api/errors/eb8d59767217958e.
Report an issue: GitHub.