{"record":{"id":"c3f16c1b9ef6fd1b","repo":"pytest-dev/pytest","slug":"cannot-write-to-stdin-c3f16c","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":277,"sourceCode":"        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\n    @property\n    def buffer(self) -> BinaryIO:\n        # The str/bytes doesn't actually matter in this type, so OK to fake.","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/capture.py#L259-L295","documentation":"Raised by DontReadFromInput.writelines() (src/_pytest/capture.py:276). Note the message capitalization ('Cannot') differs from write()'s 'cannot' at capture.py:274 - a pre-existing inconsistency. writelines() is rejected for the same reason as write(): stdin is read-only (writable() returns False).","triggerScenarios":"Calling sys.stdin.writelines(lines) on the captured pseudo-file. capture.py:276-277 raises unconditionally regardless of the iterable contents.","commonSituations":"Stream-duplication utilities, generic 'write to all standard handles' helpers, or libraries that batch-emit status to whichever stream they receive. Same class of bug as error 43 but via the batch API.","solutions":["Target sys.stdout.writelines() or sys.stderr.writelines() instead","Guard with writable() before calling writelines()","Run pytest with -s so sys.stdin is the real (still read-only) handle and the error surfaces from the OS layer with a clearer message","try/except OSError around the call if it is non-critical"],"exampleFix":"// before\nsys.stdin.writelines(lines)\n// after\nsys.stdout.writelines(lines)","handlingStrategy":"type-guard","validationCode":"import sys\nif not sys.stdin.writable():\n    pass","typeGuard":"def is_writable(stream) -> bool:\n    try:\n        return stream.writable()\n    except Exception:\n        return False","tryCatchPattern":"from io import UnsupportedOperation\ntry:\n    sys.stdin.writelines(lines)\nexcept UnsupportedOperation:\n    sys.stdout.writelines(lines)","preventionTips":["Route batch writes through writable() checks","Audit 'write to all standard streams' helpers - stdin should be excluded","Run pytest with -s if your test genuinely exercises stdin write paths"],"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"}