{"record":{"id":"68298111076c695a","repo":"unclecode/crawl4ai","slug":"cannot-get-terminal-attributes-e","errorCode":null,"errorMessage":"Cannot get terminal attributes: {e}","messagePattern":"Cannot get terminal attributes: (.+?)","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"warning","filePath":"crawl4ai/browser_profiler.py","lineNumber":272,"sourceCode":"        try:\n            import termios\n            import tty\n            import select\n        except ImportError:\n            raise ImportError(\"termios/tty/select modules not available on this platform\")\n        \n        # Get stdin file descriptor\n        try:\n            fd = sys.stdin.fileno()\n        except (AttributeError, OSError):\n            raise ImportError(\"stdin is not a terminal\")\n        \n        # Save original terminal settings\n        old_settings = None\n        try:\n            old_settings = termios.tcgetattr(fd)\n        except termios.error as e:\n            raise ImportError(f\"Cannot get terminal attributes: {e}\")\n        \n        try:\n            # Switch to non-canonical mode (cbreak mode)\n            tty.setcbreak(fd)\n            \n            while True:\n                try:\n                    # Use select to check if input is available (non-blocking)\n                    # Timeout of 0.5 seconds to periodically check browser process\n                    readable, _, _ = select.select([sys.stdin], [], [], 0.5)\n                    \n                    if readable:\n                        # Read one character\n                        key = sys.stdin.read(1)\n                        \n                        if key and key.lower() == \"q\":\n                            self.logger.info(\n                                self._get_quit_message(tag),","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/browser_profiler.py#L254-L290","documentation":"_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.","triggerScenarios":"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.","commonSituations":"docker exec without -t; CI runners; nohup with output redirection; IDE consoles providing a non-tty stdin; Windows-WSL edge cases.","solutions":["Run in a real terminal; for Docker use docker run -it.","Pre-check with sys.stdin.isatty() (and optionally termios.tcgetattr in a try) before starting interactive profiling.","Use non-interactive profiling options when a TTY is unavailable."],"exampleFix":"# before\nawait profiler.interactive_profile()  # inside docker exec (no -t) -> ImportError\n\n# after\nimport sys, termios\nif not sys.stdin.isatty():\n    raise SystemExit('run with a TTY (docker run -it) or use non-interactive mode')\nawait profiler.interactive_profile()","handlingStrategy":"validation","validationCode":"import sys, termios\ndef terminal_attributes_readable() -> bool:\n    if not sys.stdin.isatty():\n        return False\n    try:\n        termios.tcgetattr(sys.stdin.fileno())\n        return True\n    except termios.error:\n        return False","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use docker run -it / docker exec -it so a pseudo-TTY is attached.","Probe tcgetattr before entering interactive listeners.","Avoid nohup/output redirection for interactive flows."],"tags":["browser-profiler","tty","termios","environment"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}