pytest-dev/pytest · error · UnsupportedOperation

redirected stdin is pseudofile, has no tell()

Error message

redirected stdin is pseudofile, has no tell()

What it means

Raised by DontReadFromInput.tell() (src/_pytest/capture.py:267). tell() is unsupported because the redirected stdin pseudo-file keeps no position cursor; pytest raises UnsupportedOperation to surface the misuse rather than return a fabricated position. seekable()/writable()/readable() all return False to advertise this.

Solutions

  1. Disable capture with -s or --capture=no for that test/run
  2. Wrap the tell() call in try/except (OSError, ValueError) - UnsupportedOperation subclasses both
  3. Inject an io.StringIO into sys.stdin before the call so tell() is real
  4. Use the capsys/capfd fixture's stop()/resume() around the offending code

Example fix

// before
pos = sys.stdin.tell()
// after
try:
    pos = sys.stdin.tell()
except OSError:
    pos = -1
Defensive patterns

Strategy: try-catch

Validate before calling

import sys
# No probe method for tell(); must rely on seekable() as a proxy
if not sys.stdin.seekable():
    pass

Type guard

def safe_tell(stream) -> int | None:
    try:
        return stream.tell()
    except OSError:
        return None

Try / catch

try:
    pos = sys.stdin.tell()
except OSError:
    pos = None

Prevention

When it happens

Trigger: Calling sys.stdin.tell() in a test while the default capture is active. tell() at capture.py:267 always raises; there is no probe like seekable() for tell, so the call must be guarded by the caller.

Common situations: Logging libraries, terminal UIs (rich, tqdm), and test harnesses that record the current stream position before/after reads. Triggered when such code runs against sys.stdin under default pytest capture.

Related errors


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

Appendix: source

Thrown at src/_pytest/capture.py:268

        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()")

    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,

View on GitHub (pinned to 0d6fbdeffa)