{"record":{"id":"d617b6ba9328be0f","repo":"SeleniumHQ/selenium","slug":"event-listener-must-be-a-subclass-of-abstractevent","errorCode":null,"errorMessage":"Event listener must be a subclass of AbstractEventListener","messagePattern":"Event listener must be a subclass of AbstractEventListener","errorType":"exception","errorClass":"WebDriverException","httpStatus":null,"severity":"error","filePath":"py/selenium/webdriver/support/event_firing_webdriver.py","lineNumber":73,"sourceCode":"            from selenium.webdriver.support.events import EventFiringWebDriver, AbstractEventListener\n\n\n            class MyListener(AbstractEventListener):\n                def before_navigate_to(self, url, driver):\n                    print(\"Before navigate to %s\" % url)\n\n                def after_navigate_to(self, url, driver):\n                    print(\"After navigate to %s\" % url)\n\n\n            driver = Firefox()\n            ef_driver = EventFiringWebDriver(driver, MyListener())\n            ef_driver.get(\"http://www.google.co.in/\")\n        \"\"\"\n        if not isinstance(driver, WebDriver):\n            raise WebDriverException(\"A WebDriver instance must be supplied\")\n        if not isinstance(event_listener, AbstractEventListener):\n            raise WebDriverException(\"Event listener must be a subclass of AbstractEventListener\")\n        self._driver = driver\n        # this is valid, but type checkers don't like dynamically assigning to a method\n        self._driver._wrap_value = self._wrap_value  # type: ignore\n        self._listener = event_listener\n\n    @property\n    def wrapped_driver(self) -> WebDriver:\n        \"\"\"Returns the WebDriver instance wrapped by this EventsFiringWebDriver.\"\"\"\n        return self._driver\n\n    def get(self, url: str) -> None:\n        self._dispatch(\"navigate_to\", (url, self._driver), \"get\", (url,))\n\n    def back(self) -> None:\n        self._dispatch(\"navigate_back\", (self._driver,), \"back\", ())\n\n    def forward(self) -> None:\n        self._dispatch(\"navigate_forward\", (self._driver,), \"forward\", ())","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/py/selenium/webdriver/support/event_firing_webdriver.py#L55-L91","documentation":"Second constructor guard for EventFiringWebDriver: the listener must be an instance of AbstractEventListener. A plain object, dict, or function raises WebDriverException.","triggerScenarios":"EventFiringWebDriver(driver, some_function), passing a dict, or a listener class that does not inherit AbstractEventListener.","commonSituations":"Writing an ad-hoc listener without extending the base class, or passing a listener factory instead of an instance.","solutions":["Subclass AbstractEventListener (or inherit it) and pass an instance.","Verify isinstance(listener, AbstractEventListener) before constructing."],"exampleFix":"# before\nclass MyListener:                 # no base class\n    def after_get(self, d): ...\nef = EventFiringWebDriver(driver, MyListener())\n\n# after\nfrom selenium.webdriver.support.abstract_event_listener import AbstractEventListener\nclass MyListener(AbstractEventListener):\n    def after_get(self, d): ...\nef = EventFiringWebDriver(driver, MyListener())","handlingStrategy":"type-guard","validationCode":"from selenium.webdriver.support.abstract_event_listener import AbstractEventListener\nif not isinstance(listener, AbstractEventListener):\n    raise TypeError(\"listener must extend AbstractEventListener\")","typeGuard":"from selenium.webdriver.support.abstract_event_listener import AbstractEventListener\ndef is_event_listener(v) -> bool:\n    return isinstance(v, AbstractEventListener)","tryCatchPattern":null,"preventionTips":["Always extend AbstractEventListener when writing listeners.","Pass a listener instance, not a class or factory."],"tags":["events","wrapper","validation"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}