{"record":{"id":"a695831d067973a2","repo":"pytest-dev/pytest","slug":"cannot-truncate-stdin","errorCode":null,"errorMessage":"cannot truncate stdin","messagePattern":"cannot truncate stdin","errorType":"exception","errorClass":"UnsupportedOperation","httpStatus":null,"severity":"error","filePath":"src/_pytest/capture.py","lineNumber":271,"sourceCode":"        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\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,","sourceCodeStart":253,"sourceCodeEnd":289,"githubUrl":"https://github.com/pytest-dev/pytest/blob/0d6fbdeffa57c796123f62f81f7dd370d9b7ecdc/src/_pytest/capture.py#L253-L289","documentation":"Raised by DontReadFromInput.truncate() (src/_pytest/capture.py:270). truncate() is rejected because the pseudo-file backing redirected stdin is read-only and not size-addressable; pytest raises UnsupportedOperation rather than silently no-op. writable() returns False to advertise.","triggerScenarios":"Invoking sys.stdin.truncate([size]) while capture is on. capture.py:270-271 raises unconditionally with no probe method (truncate has no standard boolean predicate), so the call must be wrapped.","commonSituations":"Edge case from stream-rewriting helpers, mock libraries that walk file objects, or io.MultiFile-style code that calls truncate() defensively on every handle including stdin.","solutions":["Guard the call: only truncate() on objects whose writable() returns True","Disable capture with -s so sys.stdin is the real stream","try/except OSError around the truncate call","Stop the capture fixture (capsys.stop()) before calling truncate"],"exampleFix":"// before\nsys.stdin.truncate(0)\n// after\nif sys.stdin.writable():\n    sys.stdin.truncate(0)","handlingStrategy":"try-catch","validationCode":"import sys\nif not sys.stdin.writable():\n    pass","typeGuard":"def can_truncate(stream) -> bool:\n    try:\n        return stream.writable()\n    except Exception:\n        return False","tryCatchPattern":"try:\n    sys.stdin.truncate(size)\nexcept OSError:\n    pass","preventionTips":["Guard truncate() with writable() to skip read-only pseudo-files","Avoid calling truncate() on stdin in any code path - it is rarely meaningful","Use capsys.stop()/capfd.stop() around code that legitimately needs to mutate stdin"],"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"}