unclecode/crawl4ai · warning · ImportError

termios/tty/select modules not available on this platform

Error message

termios/tty/select modules not available on this platform

What it means

BrowserProfiler._listen_unix imports termios/tty/select and converts ImportError into this message. On Unix-likes these are stdlib and virtually always present; failure indicates a non-Unix platform (Windows) or a stripped Python build (termios excluded), i.e. the Unix listener was invoked where it cannot run.

Source

Thrown at crawl4ai/browser_profiler.py:259

                    return
                
                # Small delay to prevent busy waiting
                await asyncio.sleep(0.1)
                
            except Exception as e:
                self.logger.warning(f"Error in Windows keyboard listener: {e}", tag=tag)
                # Continue trying instead of failing completely
                await asyncio.sleep(0.1)
                continue
    
    async def _listen_unix(self, user_done_event: asyncio.Event, check_browser_process, tag: str):
        """Unix/Linux/macOS keyboard listener using termios and select."""
        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)
            

View on GitHub (pinned to 7e80152142)

Solutions

  1. Use the profiler's public interactive method which dispatches per OS.
  2. Gate manual calls: choose _listen_windows when sys.platform == 'win32'.
  3. On stripped Python builds, install a full CPython interpreter.

Example fix

# before
await profiler._listen_unix(event, check_proc, 'PROFILE')  # on Windows -> ImportError

# after
import sys
listener = profiler._listen_windows if sys.platform == 'win32' else profiler._listen_unix
await listener(event, check_proc, 'PROFILE')
Defensive patterns

Strategy: validation

Validate before calling

import sys
if sys.platform == 'win32':
    raise OSError('Unix keyboard listener requires a Unix-like platform')

Type guard

import sys
def is_unix() -> bool:
    return sys.platform != 'win32'

Prevention

When it happens

Trigger: Calling _listen_unix() on Windows; a minimal/embedded Python build compiled without termios; unusual environments like some WASM/pyodide runtimes that lack termios.

Common situations: Cross-platform code calling the private listener without a platform check; exotic Python distributions; test harnesses invoking internals on the wrong OS.

Related errors


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