pytest-dev/pytest · error · UnsupportedOperation
Cannot write to stdin
Error message
Cannot write to stdin
What it means
Raised by DontReadFromInput.writelines() (src/_pytest/capture.py:276). Note the message capitalization ('Cannot') differs from write()'s 'cannot' at capture.py:274 - a pre-existing inconsistency. writelines() is rejected for the same reason as write(): stdin is read-only (writable() returns False).
Solutions
- Target sys.stdout.writelines() or sys.stderr.writelines() instead
- Guard with writable() before calling writelines()
- Run pytest with -s so sys.stdin is the real (still read-only) handle and the error surfaces from the OS layer with a clearer message
- try/except OSError around the call if it is non-critical
Example fix
// before sys.stdin.writelines(lines) // after sys.stdout.writelines(lines)
Defensive patterns
Strategy: type-guard
Validate before calling
import sys
if not sys.stdin.writable():
pass Type guard
def is_writable(stream) -> bool:
try:
return stream.writable()
except Exception:
return False Try / catch
from io import UnsupportedOperation
try:
sys.stdin.writelines(lines)
except UnsupportedOperation:
sys.stdout.writelines(lines) Prevention
- Route batch writes through writable() checks
- Audit 'write to all standard streams' helpers - stdin should be excluded
- Run pytest with -s if your test genuinely exercises stdin write paths
When it happens
Trigger: Calling sys.stdin.writelines(lines) on the captured pseudo-file. capture.py:276-277 raises unconditionally regardless of the iterable contents.
Common situations: Stream-duplication utilities, generic 'write to all standard handles' helpers, or libraries that batch-emit status to whichever stream they receive. Same class of bug as error 43 but via the batch API.
Related errors
- cannot truncate stdin
- cannot write to stdin
- redirected stdin is pseudofile, has no seek(int)
- redirected stdin is pseudofile, has no tell()
- pytest: reading from stdin while output is captured! …
AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11).
Data as JSON: /api/errors/c3f16c1b9ef6fd1b.
Report an issue: GitHub.
Appendix: 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 0d6fbdeffa)