unclecode/crawl4ai · warning · ImportError

msvcrt module not available on this platform

Error message

msvcrt module not available on this platform

What it means

BrowserProfiler._listen_windows is the Windows keyboard listener used during interactive profiling; it imports msvcrt and converts an ImportError into this clearer ImportError. Seeing it means the method ran on a platform where msvcrt does not exist (any non-Windows OS), i.e. the wrong listener was selected for the OS.

Source

Thrown at crawl4ai/browser_profiler.py:201

    def _is_linux(self) -> bool:
        """Check if running on Linux platform."""
        return sys.platform.startswith('linux')
    
    def _get_quit_message(self, tag: str) -> str:
        """Get appropriate quit message based on context."""
        if tag == "PROFILE":
            return "Closing browser and saving profile..."
        elif tag == "CDP":
            return "Closing browser..."
        else:
            return "Closing browser..."
    
    async def _listen_windows(self, user_done_event, check_browser_process, tag: str):
        """Windows-specific keyboard listener using msvcrt."""
        try:
            import msvcrt
        except ImportError:
            raise ImportError("msvcrt module not available on this platform")
        
        while True:
            try:
                # Check for keyboard input
                if msvcrt.kbhit():
                    raw = msvcrt.getch()
                    
                    # Handle Unicode decoding more robustly
                    key = None
                    try:
                        key = raw.decode("utf-8")
                    except UnicodeDecodeError:
                        try:
                            # Try different encodings
                            key = raw.decode("latin1")
                        except UnicodeDecodeError:
                            # Skip if we can't decode
                            continue

View on GitHub (pinned to 7e80152142)

Solutions

  1. Don't call _listen_windows directly; use the profiler's public interactive flow which picks _listen_unix on non-Windows platforms.
  2. On Unix use _listen_unix (termios-based) if you must call a listener manually.
  3. Gate any direct call behind sys.platform == 'win32'.

Example fix

# before
await profiler._listen_windows(event, check_proc, 'PROFILE')  # on Linux -> 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('Windows keyboard listener requires Windows')

Type guard

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

Prevention

When it happens

Trigger: Calling _listen_windows() directly on Linux/macOS, or a dispatch bug/environment where sys.platform detection routed to the Windows listener on a Unix system. Normal flows call it only on win32.

Common situations: Monkeypatching or subclassing the profiler and calling private listeners in tests on Unix; running under WSL interop quirks where platform detection misfires; importing and invoking internal helpers directly.

Related errors


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