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

  1. Run with -s / --capture=no to keep real stdin.
  2. Route writelines to the correct stream (sys.stdout/stderr.writelines(lines)).
  3. monkeypatch sys.stdin with an io.StringIO that supports writelines for the test.
  4. 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

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


AI-assisted analysis of pytest-dev/pytest@98b357f69e (2026-08-04). Data as JSON: /data/errors/c3f16c1b9ef6fd1b.json. Report an issue: GitHub.