{"record":{"id":"419b1850df40473b","repo":"pytest-dev/pytest","slug":"redirected-stdin-is-pseudofile-has-no-seek-int","errorCode":null,"errorMessage":"redirected stdin is pseudofile, has no seek(int)","messagePattern":"redirected stdin is pseudofile, has no seek\\(int\\)","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"src/_pytest/capture.py","lineNumber":262,"sourceCode":"        return self\n\n    def fileno(self) -> int:\n        raise UnsupportedOperation(\"redirected stdin is pseudofile, has no fileno()\")\n\n    def flush(self) -> None:\n        raise UnsupportedOperation(\"redirected stdin is pseudofile, has no flush()\")\n\n    def isatty(self) -> bool:\n        return False\n\n    def close(self) -> None:\n        pass\n\n    def readable(self) -> bool:\n        return False\n\n    def seek(self, offset: int, whence: int = 0) -> int:\n        raise UnsupportedOperation(\"redirected stdin is pseudofile, has no seek(int)\")\n\n    def seekable(self) -> bool:\n        return False\n\n    def tell(self) -> int:\n        raise UnsupportedOperation(\"redirected stdin is pseudofile, has no tell()\")\n\n    def truncate(self, size: int | None = None) -> int:\n        raise UnsupportedOperation(\"cannot truncate stdin\")\n\n    def write(self, data: str) -> int:\n        raise UnsupportedOperation(\"cannot write to stdin\")\n\n    def writelines(self, lines: Iterable[str]) -> None:\n        raise UnsupportedOperation(\"Cannot write to stdin\")\n\n    def writable(self) -> bool:\n        return False","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/capture.py#L244-L280","documentation":"Raised by DontReadFromInput.seek() (src/_pytest/capture.py:261). When pytest captures output (default behavior), it replaces sys.stdin with a DontReadFromInput pseudo-file that blocks all read/seek/tell/write operations. seek() raises UnsupportedOperation (an OSError/ValueError subclass) because redirected stdin is not a real file and has no position cursor. The class advertises this via seekable() returning False.","triggerScenarios":"Calling sys.stdin.seek(offset[, whence]) inside a test while output capture is on (the default). The seek() call at capture.py:261 unconditionally raises; seekable() at capture.py:264 returns False so callers that probe first are safe.","commonSituations":"Test helpers or libraries under test (CLIs using prompt_toolkit, doctest harnesses, replay frameworks) call sys.stdin.seek(0) to rewind piped input. Also triggered when a test stubs sys.stdin with a real file then pytest's capture re-wraps it.","solutions":["Run pytest with -s (or --capture=no) to disable stdin replacement entirely","Inside the test, stop capture explicitly via capture_fixture.stop() (capsys.stop()/capfd.stop()) before seeking","Replace sys.stdin with an io.StringIO before the seek; do not rely on the captured pseudo-file","Gate the seek with `if sys.stdin.seekable():` so DontReadFromInput at capture.py:264 short-circuits"],"exampleFix":"// before\nsys.stdin.seek(0)\n// after\nif sys.stdin.seekable():\n    sys.stdin.seek(0)","handlingStrategy":"try-catch","validationCode":"import sys\nif not sys.stdin.seekable():\n    # pytest capture is active; skip seek\n    pass","typeGuard":"def can_seek(stream) -> bool:\n    try:\n        return stream.seekable()\n    except Exception:\n        return False","tryCatchPattern":"from io import UnsupportedOperation\ntry:\n    sys.stdin.seek(0)\nexcept (UnsupportedOperation, OSError):\n    # pytest DontReadFromInput - capture is on\n    pass","preventionTips":["Always probe seekable() before calling seek() on a stream you do not own","Run pytest with -s for tests that genuinely need real stdin semantics","Inject io.StringIO into sys.stdin in fixtures rather than relying on pytest's pseudo-file"],"tags":["capture","stdin","io","unsupported-operation"],"backgroundTag":null,"analyzedSha":"0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc","analyzedAt":"2026-08-11T20:52:36.969Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}