pytest-dev/pytest · error · UnsupportedOperation
Cannot write to stdin
Error message
Cannot write to stdin
What it means
Raised by DontReadFromInput.writelines() (capture.py:276-277), the batch write counterpart of write(). Like write(), it is intentionally disabled because the captured stdin pseudo-file is not writable (writable() returns False). The class replaces sys.stdin during captured test runs to prevent accidental I/O on a redirected stream.
Source
Thrown at src/_pytest/capture.py:277
return False
def seek(self, offset: int, whence: int = 0) -> int:
raise UnsupportedOperation("redirected stdin is pseudofile, has no seek(int)")
def seekable(self) -> bool:
return False
def tell(self) -> int:
raise UnsupportedOperation("redirected stdin is pseudofile, has no tell()")
def truncate(self, size: int | None = None) -> int:
raise UnsupportedOperation("cannot truncate stdin")
def write(self, data: str) -> int:
raise UnsupportedOperation("cannot write to stdin")
def writelines(self, lines: Iterable[str]) -> None:
raise UnsupportedOperation("Cannot write to stdin")
def writable(self) -> bool:
return False
def __enter__(self) -> Self:
return self
def __exit__(
self,
type: type[BaseException] | None,
value: BaseException | None,
traceback: TracebackType | None,
) -> None:
pass
@property
def buffer(self) -> BinaryIO:
# The str/bytes doesn't actually matter in this type, so OK to fake.View on GitHub (pinned to 98b357f69e)
Solutions
- Run with -s / --capture=no to keep real stdin.
- Route writelines to the correct stream (sys.stdout/stderr.writelines(lines)).
- monkeypatch sys.stdin with an io.StringIO that supports writelines for the test.
- Check `getattr(stream, 'writable', lambda: False)()` before calling writelines.
Example fix
// before sys.stdin.writelines(lines) # after sys.stdout.writelines(lines)
Defensive patterns
Strategy: type-guard
Validate before calling
def safe_writelines(stream, lines):
if getattr(stream, 'writable', lambda: False)():
stream.writelines(lines) Type guard
def is_writable(stream) -> bool:
return bool(getattr(stream, 'writable', lambda: False)()) Try / catch
from io import UnsupportedOperation
try:
sys.stdin.writelines(lines)
except UnsupportedOperation:
sys.stdout.writelines(lines) Prevention
- Target writelines at stdout/stderr or a buffer, never stdin.
- For libs that call writelines on a passed stream, inject an io.StringIO in tests.
- Use -s to disable the DontReadFromInput replacement.
When it happens
Trigger: Calling sys.stdin.writelines(iterable), or handing sys.stdin to an API that uses writelines (e.g. some serializers/socket wrappers), while capture is on and stdin is the DontReadFromInput sentinel.
Common situations: Porting code from a real TTY where writelines on stdin was tolerated; test fixtures that pass sys.stdin as a 'file-like' sink; libraries that optimize bulk output via writelines regardless of the stream role.
Related errors
- cannot write to stdin
- pytest: reading from stdin while output is captured! Consid
- redirected stdin is pseudofile, has no fileno()
- redirected stdin is pseudofile, has no flush()
- redirected stdin is pseudofile, has no seek(int)
AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04).
Data as JSON: /data/errors/c3f16c1b9ef6fd1b.json.
Report an issue: GitHub.