{"record":{"id":"005ae681fbcd332a","repo":"python/cpython","slug":"termios-failure-e-args-1","errorCode":null,"errorMessage":"termios failure ({e.args[1]})","messagePattern":"termios failure \\((.+?)\\)","errorType":"console","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"Lib/_pyrepl/unix_console.py","lineNumber":225,"sourceCode":"        - f_out (int or file-like object): Output file descriptor or object.\n        - term (str): Terminal name.\n        - encoding (str): Encoding to use for I/O operations.\n        \"\"\"\n        super().__init__(f_in, f_out, term, encoding)\n\n        self.pollob = poll()\n        self.pollob.register(self.input_fd, select.POLLIN)\n        self.terminfo = terminfo.TermInfo(term or None)\n        self.term = term\n        self.is_apple_terminal = (\n            platform.system() == \"Darwin\"\n            and os.getenv(\"TERM_PROGRAM\") == \"Apple_Terminal\"\n        )\n\n        try:\n            self.__input_fd_set(tcgetattr(self.input_fd), ignore=frozenset())\n        except _error as e:\n            raise RuntimeError(f\"termios failure ({e.args[1]})\")\n\n        @overload\n        def _my_getstr(\n            cap: str, optional: Literal[False] = False\n        ) -> bytes: ...\n\n        @overload\n        def _my_getstr(cap: str, optional: bool) -> bytes | None: ...\n\n        def _my_getstr(cap: str, optional: bool = False) -> bytes | None:\n            r = self.terminfo.get(cap)\n            if not optional and r is None:\n                raise InvalidTerminal(\n                    f\"terminal doesn't have the required {cap} capability\"\n                )\n            return r\n\n        self._bel = _my_getstr(\"bel\")","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pyrepl/unix_console.py#L207-L243","documentation":"RuntimeError raised in UnixConsole.__init__ (Lib/_pyrepl/unix_console.py). During console setup the code calls tcgetattr on the input fd and pipes it through __input_fd_set; if that underlying termios call fails (termios.error), the code re-raises as RuntimeError with the OS error string from e.args[1] (e.g. 'Inappropriate ioctl for device').","triggerScenarios":"Constructing UnixConsole (or starting the pyrepl REPL) when the input fd is not a terminal or the termios state is unavailable: stdin redirected to a file/pipe despite other checks passing, fd already closed, or a PTY that does not support termios ioctls. tcgetattr raising termios.error is the trigger.","commonSituations":"Embedding pyrepl in tools where stdin was swapped after import-time isatty checks; spawning the REPL under process supervisors that give a half-open PTY; race where the tty is closed by another thread between the isatty check and tcgetattr; exotic terminals (some CI docker setups without -t).","solutions":["Ensure the process actually owns a real terminal before constructing UnixConsole: run docker/exec with -t, allocate a PTY (pty.openpty/os.openpty) and dup it onto fd 0.","Check os.isatty(sys.stdin.fileno()) immediately before construction, not only at import time.","If embedding, catch RuntimeError here and fall back to plain input() or readline-based interaction."],"exampleFix":"# before\nconsole = UnixConsole()  # RuntimeError: termios failure (...) when stdin lacks termios\n\n# after\nimport os, sys\nif not os.isatty(sys.stdin.fileno()):\n    raise SystemExit('pyrepl needs a tty on stdin; run with a pty')\nconsole = UnixConsole()","handlingStrategy":"try-catch","validationCode":"import os, sys\n\ndef console_ready():\n    try:\n        return os.isatty(sys.stdin.fileno())\n    except (OSError, ValueError):\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    from _pyrepl.unix_console import UnixConsole\n    console = UnixConsole()\nexcept (RuntimeError, OSError) as e:\n    raise SystemExit(f'cannot start interactive console: {e}') from e","preventionTips":["Allocate a real PTY before constructing UnixConsole (docker -t, pexpect, os.openpty).","Check isatty immediately before use, not once at import.","Catch RuntimeError/OSError at console construction and degrade to input() in embedded tools."],"tags":["python","pyrepl","termios","tty","unix","initialization"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}