{"record":{"id":"6812a3b1f0cc6311","repo":"unclecode/crawl4ai","slug":"invalid-browser-type-must-be-one-of-join-b","errorCode":null,"errorMessage":"Invalid browser type. Must be one of: {', '.join(browsers.keys())}","messagePattern":"Invalid browser type\\. Must be one of: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"crawl4ai/utils.py","lineNumber":672,"sourceCode":"        raise RuntimeError(f\"Unsupported browser type: {browser_type}\")\n\n    # Check if a path has already been saved for this browser type\n    home_folder = get_home_folder()\n    path_file = os.path.join(home_folder, f\"{browser_type.lower()}.path\")\n    if os.path.exists(path_file):\n        with open(path_file, \"r\") as f:\n            return f.read()\n\n    from playwright.async_api import async_playwright\n    async with async_playwright() as p:\n        browsers = {\n            'chromium': p.chromium,\n            'firefox': p.firefox, \n            'webkit': p.webkit\n        }\n        \n        if browser_type.lower() not in browsers:\n            raise ValueError(\n                f\"Invalid browser type. Must be one of: {', '.join(browsers.keys())}\"\n            )\n            \n        # Save the path int the crawl4ai home folder\n        home_folder = get_home_folder()\n        browser_path = browsers[browser_type.lower()].executable_path\n        if not browser_path:\n            raise RuntimeError(f\"Browser executable not found for type: {browser_type}\")\n        # Save the path in a text file with browser type name\n        with open(os.path.join(home_folder, f\"{browser_type.lower()}.path\"), \"w\") as f:\n            f.write(browser_path)\n        \n        return browser_path\n\ndef beautify_html(escaped_html):\n    \"\"\"\n    Beautifies an escaped HTML string.\n","sourceCodeStart":654,"sourceCodeEnd":690,"githubUrl":"https://github.com/unclecode/crawl4ai/blob/7e801521428ee12509994d39151006f64055ebe3/crawl4ai/utils.py#L654-L690","documentation":"ValueError raised in the Playwright-based path-resolution branch of get_browser_executable_path when browser_type.lower() is not a key of the locally built browsers dict ({'chromium','firefox','webkit'}). This check runs after a cached .path file lookup misses, right before querying Playwright's executable_path.","triggerScenarios":"Calling the async setup utility with an unrecognized browser type when no cached path file exists for it — the code lowercases the input then requires one of Playwright's three browser names.","commonSituations":"Same misuse class as the sibling RuntimeError: 'chrome' vs 'chromium', vendor names, or passing a full executable path instead of a browser type. The lowercase handling here means uppercase 'CHROMIUM' works, but 'chrome' still fails.","solutions":["Pass one of the canonical Playwright names: 'chromium', 'firefox', 'webkit' (any case).","Map vendor aliases to Playwright names before calling.","Prefer crawl4ai's higher-level setup API (crawl4ai-setup) which handles browser installation and naming for you."],"exampleFix":"# before\npath = await get_browser_executable_path(\"Chrome\")  # ValueError: Invalid browser type. Must be one of: chromium, firefox, webkit\n\n# after\npath = await get_browser_executable_path(\"chromium\")","handlingStrategy":"type-guard","validationCode":"BROWSERS = {\"chromium\", \"firefox\", \"webkit\"}\n\nif browser_type.lower() not in BROWSERS:\n    raise ValueError(f\"browser_type must be one of {sorted(BROWSERS)}, got {browser_type!r}\")\npath = await get_browser_executable_path(browser_type)","typeGuard":"def is_playwright_browser(name: str) -> bool:\n    return isinstance(name, str) and name.lower() in {\"chromium\", \"firefox\", \"webkit\"}","tryCatchPattern":"try:\n    path = await get_browser_executable_path(name)\nexcept ValueError as e:\n    if 'Invalid browser type' in str(e):\n        name = canonical_browser(name)  # retry with normalized alias\n        path = await get_browser_executable_path(name)","preventionTips":["Any casing works here, but the name itself must be one of the three Playwright browsers.","Validate config values at load time with the set membership check above.","Prefer crawl4ai's setup entry points which normalize browser names for you."],"tags":["browser","playwright","validation","setup"],"backgroundTag":null,"analyzedSha":"7e801521428ee12509994d39151006f64055ebe3","analyzedAt":"2026-08-14T20:46:20.673Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}