{"record":{"id":"16bd920d0b897516","repo":"SeleniumHQ/selenium","slug":"failed-to-load-mutation-listener-js","errorCode":null,"errorMessage":"Failed to load mutation-listener.js","messagePattern":"Failed to load mutation-listener\\.js","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/common/log.py","lineNumber":53,"sourceCode":"\n\nclass Log:\n    \"\"\"Class for accessing logging APIs using the WebDriver Bidi protocol.\n\n    This class is not to be used directly and should be used from the\n    webdriver base classes.\n    \"\"\"\n\n    def __init__(self, driver, bidi_session) -> None:\n        self.driver = driver\n        self.session = bidi_session.session\n        self.cdp = bidi_session.cdp\n        self.devtools = bidi_session.devtools\n        _pkg = \".\".join(__name__.split(\".\")[:-1])\n        # Ensure _mutation_listener_js is not None before decoding\n        _mutation_listener_js_bytes: bytes | None = pkgutil.get_data(_pkg, \"mutation-listener.js\")\n        if _mutation_listener_js_bytes is None:\n            raise ValueError(\"Failed to load mutation-listener.js\")\n        self._mutation_listener_js = _mutation_listener_js_bytes.decode(\"utf8\").strip()\n\n    @asynccontextmanager\n    async def mutation_events(self) -> AsyncGenerator[dict[str, Any], None]:\n        \"\"\"Listen for mutation events and emit them as they are found.\n\n        .. deprecated::\n            Use ``driver.script.add_dom_mutation_handler()`` instead,\n            which uses the WebDriver BiDi protocol.\n\n        Example:\n               async with driver.log.mutation_events() as event:\n                    pages.load(\"dynamic.html\")\n                    driver.find_element(By.ID, \"reveal\").click()\n                    WebDriverWait(driver, 5)\\\n                        .until(EC.visibility_of(driver.find_element(By.ID, \"revealed\")))\n\n                assert event[\"attribute_name\"] == \"style\"","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/common/log.py#L35-L71","documentation":"The Log class loads mutation-listener.js from the selenium webdriver common package via pkgutil.get_data at construction time. If the resource is absent (returns None), a ValueError is raised, meaning the installed selenium package is incomplete or the resource was stripped. This indicates a packaging/corruption problem rather than normal user input.","triggerScenarios":"Constructing/accessing driver.log (the Log instance) when the mutation-listener.js resource is missing from the installed selenium distribution — e.g. a broken wheel, a partial editable install, or a zipimport/PyInstaller bundle that excludes non-.py files.","commonSituations":"Frozen/packaged apps (PyInstaller, cx_Freeze, zipapp) that do not include package data files. A manually edited or corrupted site-packages selenium install. Running from a source checkout where common/mutation-listener.js was deleted or not checked out.","solutions":["Reinstall selenium cleanly: `pip install --force-reinstall selenium` to restore the resource.","If packaging with PyInstaller, add mutation-listener.js to package data / --add-data.","Verify the file exists: check selenium/webdriver/common/mutation-listener.js in your install.","Prefer the non-deprecated BiDi API driver.script.add_dom_mutation_handler() which does not need this resource."],"exampleFix":"# before (broken install, resource missing)\nasync with driver.log.mutation_events() as event:  # raises at Log init\n    ...\n\n# after (use modern BiDi handler instead, no js resource needed)\nawait driver.script.add_dom_mutation_handler(handler)","handlingStrategy":"validation","validationCode":"import pkgutil\n_pkg = 'selenium.webdriver.common'\nmissing = pkgutil.get_data(_pkg, 'mutation-listener.js') is None\nif missing:\n    raise RuntimeError('mutation-listener.js missing; reinstall selenium or use BiDi API')","typeGuard":null,"tryCatchPattern":"try:\n    log = driver.log\nexcept ValueError as e:\n    if 'mutation-listener.js' in str(e):\n        # packaging issue; fall back to BiDi handler\n        await driver.script.add_dom_mutation_handler(handler)","preventionTips":["Include package data when freezing apps (PyInstaller --add-data).","Pin and cleanly reinstall selenium in CI images.","Prefer driver.script.add_dom_mutation_handler() over the deprecated mutation_events()."],"tags":["packaging","resource-loading","pkgutil","bidi"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}