pytest-dev/pytest · error · UnsupportedOperation

cannot write to stdin

Error message

cannot write to stdin

What it means

Raised by DontReadFromInput.write() (capture.py:273-274), the pseudo-file pytest substitutes for sys.stdin while stdout/stderr are being captured. The object is read-only by design (writable() returns False), so any attempt to write bytes/text to stdin during a captured test session raises UnsupportedOperation. It exists so that code which accidentally writes to stdin fails loudly instead of corrupting capture state.

Source

Thrown at src/_pytest/capture.py:274

        pass

    def readable(self) -> bool:
        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

View on GitHub (pinned to 98b357f69e)

Solutions

  1. Run pytest with -s (or --capture=no) to disable stdin replacement so real stdin is preserved.
  2. Stop writing to sys.stdin — redirect the write to sys.stdout/stderr or an io.StringIO buffer instead.
  3. If a third-party library writes to stdin, inject a writable dummy stream via monkeypatch.setattr(sys, 'stdin', io.StringIO()) in the fixture.
  4. Guard the call site with `if sys.stdin.writable():` before writing.

Example fix

// before
sys.stdin.write(prompt)

# after
sys.stdout.write(prompt)
Defensive patterns

Strategy: type-guard

Validate before calling

import sys
def safe_write(stream, data):
    if getattr(stream, 'writable', lambda: False)():
        return stream.write(data)
    return 0

Type guard

def is_writable(stream) -> bool:
    return bool(getattr(stream, 'writable', lambda: False)())

Try / catch

from io import UnsupportedOperation
try:
    sys.stdin.write(data)
except UnsupportedOperation:
    sys.stdout.write(data)

Prevention

When it happens

Trigger: Calling sys.stdin.write(data), print(..., file=sys.stdin), or passing the captured stdin to a function that invokes .write() on it, while pytest capture is active (default) and stdin has been replaced by DontReadFromInput. Also triggered by libraries that probe/write to file descriptors handed to them.

Common situations: Test helpers or fixtures that redirect logging/output to sys.stdin by mistake; doctest/CLI tools tested under pytest that write prompts to stdin; third-party libs (e.g. input wrappers, prompt kits) that call stdin.write during tests run without -s.

Related errors


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