pytest-dev/pytest · error · UnsupportedOperation

redirected stdin is pseudofile, has no flush()

Error message

redirected stdin is pseudofile, has no flush()

What it means

Raised by DontReadFromInput.flush() when code attempts to flush the captured stdin pseudofile. Since the pseudofile is read-only and backed by nothing, flushing is unsupported and raises UnsupportedOperation. This typically surfaces when generic IO-handling code calls flush() defensively on any stream, including stdin.

Solutions

  1. Run pytest with -s to use the real stdin (which supports flush).
  2. Monkeypatch sys.stdin to a StringIO or real file that supports flush.
  3. Guard flush calls: if hasattr(sys.stdin, 'flush') and sys.stdin is not the captured sentinel.

Example fix

// before
sys.stdin.flush()  # raises under capture
// after
monkeypatch.setattr('sys.stdin', io.StringIO())
sys.stdin.flush()
Defensive patterns

Strategy: try-catch

Validate before calling

def safe_flush(stream):
    flush = getattr(stream, 'flush', None)
    if flush is None:
        return
    try:
        flush()
    except (OSError, ValueError):
        pass

Type guard

def flush_is_supported(stream) -> bool:
    flush = getattr(stream, 'flush', None)
    if flush is None:
        return False
    try:
        flush(); return True
    except Exception:
        return False

Try / catch

try:
    sys.stdin.flush()
except (OSError, ValueError) as e:
    if 'pseudofile' in str(e):
        pass  # captured stdin; nothing to flush

Prevention

When it happens

Trigger: Code calls sys.stdin.flush(); a logging or IO helper flushes every file-like object it touches; redirect helpers that flush stdin as part of cleanup.

Common situations: Generic stream-management utilities that flush indiscriminately; porting shell-pipeline-style code that flushes all std streams.

Related errors


AI-assisted analysis of pytest-dev/pytest@0d6fbdeffa (2026-08-11). Data as JSON: /api/errors/c6e43083aa0a5c1d. Report an issue: GitHub.

Appendix: source

Thrown at src/_pytest/capture.py:250

    readline = read

    def __next__(self) -> str:
        return self.readline()

    def readlines(self, hint: int | None = -1) -> list[str]:
        raise OSError(
            "pytest: reading from stdin while output is captured!  Consider using `-s`."
        )

    def __iter__(self) -> Iterator[str]:
        return self

    def fileno(self) -> int:
        raise UnsupportedOperation("redirected stdin is pseudofile, has no fileno()")

    def flush(self) -> None:
        raise UnsupportedOperation("redirected stdin is pseudofile, has no flush()")

    def isatty(self) -> bool:
        return False

    def close(self) -> None:
        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()")

View on GitHub (pinned to 0d6fbdeffa)