unclecode/crawl4ai · warning · ImportError

Cannot get terminal attributes: {e}

Error message

Cannot get terminal attributes: {e}

What it means

_listen_unix calls termios.tcgetattr(fd) to snapshot terminal settings; failure (raised termios.error, e.g. errno 25 'Inappropriate ioctl for device') is wrapped as ImportError('Cannot get terminal attributes: ...'). Like the 'stdin is not a terminal' guard, it means the fd exists but is not a terminal device, or terminal state is otherwise unreadable.

Source

Thrown at crawl4ai/browser_profiler.py:272

        try:
            import termios
            import tty
            import select
        except ImportError:
            raise ImportError("termios/tty/select modules not available on this platform")
        
        # Get stdin file descriptor
        try:
            fd = sys.stdin.fileno()
        except (AttributeError, OSError):
            raise ImportError("stdin is not a terminal")
        
        # Save original terminal settings
        old_settings = None
        try:
            old_settings = termios.tcgetattr(fd)
        except termios.error as e:
            raise ImportError(f"Cannot get terminal attributes: {e}")
        
        try:
            # Switch to non-canonical mode (cbreak mode)
            tty.setcbreak(fd)
            
            while True:
                try:
                    # Use select to check if input is available (non-blocking)
                    # Timeout of 0.5 seconds to periodically check browser process
                    readable, _, _ = select.select([sys.stdin], [], [], 0.5)
                    
                    if readable:
                        # Read one character
                        key = sys.stdin.read(1)
                        
                        if key and key.lower() == "q":
                            self.logger.info(
                                self._get_quit_message(tag),

View on GitHub (pinned to 7e80152142)

Solutions

  1. Run in a real terminal; for Docker use docker run -it.
  2. Pre-check with sys.stdin.isatty() (and optionally termios.tcgetattr in a try) before starting interactive profiling.
  3. Use non-interactive profiling options when a TTY is unavailable.

Example fix

# before
await profiler.interactive_profile()  # inside docker exec (no -t) -> ImportError

# after
import sys, termios
if not sys.stdin.isatty():
    raise SystemExit('run with a TTY (docker run -it) or use non-interactive mode')
await profiler.interactive_profile()
Defensive patterns

Strategy: validation

Validate before calling

import sys, termios
def terminal_attributes_readable() -> bool:
    if not sys.stdin.isatty():
        return False
    try:
        termios.tcgetattr(sys.stdin.fileno())
        return True
    except termios.error:
        return False

Prevention

When it happens

Trigger: stdin connected to a pipe/pty-less subprocess where fileno() succeeded but tcgetattr fails; running under CI log collectors; some container exec sessions without a pseudo-TTY (docker run without -t); terminal detached mid-run.

Common situations: docker exec without -t; CI runners; nohup with output redirection; IDE consoles providing a non-tty stdin; Windows-WSL edge cases.

Related errors


AI-assisted analysis of unclecode/crawl4ai@7e80152142 (2026-08-14). Data as JSON: /api/errors/68298111076c695a. Report an issue: GitHub.