{"id":"4ba3d5aac88b9b59","repo":"pytest-dev/pytest","slug":"cannot-write-to-stdin","errorCode":null,"errorMessage":"cannot write to stdin","messagePattern":"cannot write to stdin","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"src/_pytest/capture.py","lineNumber":274,"sourceCode":"        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\n\n    def __enter__(self) -> Self:\n        return self\n\n    def __exit__(\n        self,\n        type: type[BaseException] | None,\n        value: BaseException | None,\n        traceback: TracebackType | None,\n    ) -> None:\n        pass\n","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/capture.py#L256-L292","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Run pytest with -s (or --capture=no) to disable stdin replacement so real stdin is preserved.","Stop writing to sys.stdin — redirect the write to sys.stdout/stderr or an io.StringIO buffer instead.","If a third-party library writes to stdin, inject a writable dummy stream via monkeypatch.setattr(sys, 'stdin', io.StringIO()) in the fixture.","Guard the call site with `if sys.stdin.writable():` before writing."],"exampleFix":"// before\nsys.stdin.write(prompt)\n\n# after\nsys.stdout.write(prompt)","handlingStrategy":"type-guard","validationCode":"import sys\ndef safe_write(stream, data):\n    if getattr(stream, 'writable', lambda: False)():\n        return stream.write(data)\n    return 0","typeGuard":"def is_writable(stream) -> bool:\n    return bool(getattr(stream, 'writable', lambda: False)())","tryCatchPattern":"from io import UnsupportedOperation\ntry:\n    sys.stdin.write(data)\nexcept UnsupportedOperation:\n    sys.stdout.write(data)","preventionTips":["Never write to sys.stdin; treat it as read-only.","Run pytest with -s when tests need real stdin semantics.","Inject io.StringIO via monkeypatch for code expecting a writable stream."],"tags":["capture","stdin","unsupported-operation","pytest"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}