python/cpython · error · RuntimeError
termios failure ({e.args[1]})
Error message
termios failure ({e.args[1]}) What it means
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').
Source
Thrown at Lib/_pyrepl/unix_console.py:225
- f_out (int or file-like object): Output file descriptor or object.
- term (str): Terminal name.
- encoding (str): Encoding to use for I/O operations.
"""
super().__init__(f_in, f_out, term, encoding)
self.pollob = poll()
self.pollob.register(self.input_fd, select.POLLIN)
self.terminfo = terminfo.TermInfo(term or None)
self.term = term
self.is_apple_terminal = (
platform.system() == "Darwin"
and os.getenv("TERM_PROGRAM") == "Apple_Terminal"
)
try:
self.__input_fd_set(tcgetattr(self.input_fd), ignore=frozenset())
except _error as e:
raise RuntimeError(f"termios failure ({e.args[1]})")
@overload
def _my_getstr(
cap: str, optional: Literal[False] = False
) -> bytes: ...
@overload
def _my_getstr(cap: str, optional: bool) -> bytes | None: ...
def _my_getstr(cap: str, optional: bool = False) -> bytes | None:
r = self.terminfo.get(cap)
if not optional and r is None:
raise InvalidTerminal(
f"terminal doesn't have the required {cap} capability"
)
return r
self._bel = _my_getstr("bel")View on GitHub (pinned to bc6749cc3b)
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.
Example fix
# before
console = UnixConsole() # RuntimeError: termios failure (...) when stdin lacks termios
# after
import os, sys
if not os.isatty(sys.stdin.fileno()):
raise SystemExit('pyrepl needs a tty on stdin; run with a pty')
console = UnixConsole() Defensive patterns
Strategy: try-catch
Validate before calling
import os, sys
def console_ready():
try:
return os.isatty(sys.stdin.fileno())
except (OSError, ValueError):
return False Try / catch
try:
from _pyrepl.unix_console import UnixConsole
console = UnixConsole()
except (RuntimeError, OSError) as e:
raise SystemExit(f'cannot start interactive console: {e}') from e Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- ENOTTY
- Windows 10 TH2 or later required
- \C must be followed by `-' (char %d of %s)
- doubled \C- (char %d of %s)
- \M must be followed by `-' (char %d of %s)
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/005ae681fbcd332a.
Report an issue: GitHub.