crewAIInc/crewAI · error · RuntimeError

Driver not initialized. Call _run first.

Error message

Driver not initialized. Call _run first.

What it means

RuntimeError raised by SeleniumScrapingTool._get_body_content when self.driver or self._by is None — i.e. the Selenium WebDriver was never initialized. The helper runs as part of content extraction after _make_request, but driver setup happens lazily in _run's __init__ path (_ensure_imports_and_driver); calling extraction before that setup, or after the driver failed to build, hits this guard. The message tells you the intended entry point is _run.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/selenium_scraping_tool/selenium_scraping_tool.py:166

    def _get_content(
        self, css_element: str | None, return_html: bool | None
    ) -> list[str]:
        content: list[str] = []

        if self._is_css_element_empty(css_element):
            content.append(self._get_body_content(return_html))
        else:
            content.extend(self._get_elements_content(css_element, return_html))

        return content

    def _is_css_element_empty(self, css_element: str | None) -> bool:
        return css_element is None or css_element.strip() == ""

    def _get_body_content(self, return_html: bool | None) -> str:
        if self.driver is None or self._by is None:
            raise RuntimeError("Driver not initialized. Call _run first.")
        body_element = self.driver.find_element(self._by.TAG_NAME, "body")

        return str(
            body_element.get_attribute("outerHTML")
            if return_html
            else body_element.text
        )

    def _get_elements_content(
        self, css_element: str | None, return_html: bool | None
    ) -> list[str]:
        if self.driver is None or self._by is None:
            raise RuntimeError("Driver not initialized. Call _run first.")
        elements_content: list[str] = []

        for element in self.driver.find_elements(self._by.CSS_SELECTOR, css_element):
            elements_content.append(  # noqa: PERF401
                element.get_attribute("outerHTML") if return_html else element.text

View on GitHub (pinned to 754d7323be)

Solutions

  1. Enter through the public API: call tool.run(...) (i.e. _run) so the driver is initialized before extraction.
  2. Verify Chrome and chromedriver are installed/compatible so webdriver.Chrome() actually succeeds during setup.
  3. Do not call private helpers (_get_body_content etc.) directly; if you must, ensure a prior successful _run.

Example fix

# before
content = tool._get_body_content(return_html=False)  # RuntimeError

# after
content = tool.run(website_url="https://example.com")  # _run initializes driver first
Defensive patterns

Strategy: validation

Validate before calling

def driver_ready(tool) -> bool:
    return tool.driver is not None and getattr(tool, "_by", None) is not None

Try / catch

try:
    content = tool.run(website_url=url)  # public path initializes the driver
except RuntimeError as e:
    if "Driver not initialized" in str(e):
        raise RuntimeError("browser setup failed — check Chrome/chromedriver install") from e
    raise

Prevention

When it happens

Trigger: Invoking internal helpers (_get_body_content / the content pipeline) directly on a tool whose _run never completed driver initialization; driver creation failed earlier (e.g. Chrome binary missing) leaving driver None; calling methods on a fresh instance constructed without kwargs that trigger extraction before setup.

Common situations: Subclassing or reusing SeleniumScrapingTool internals in custom flows; Chrome/chromedriver not installed so webdriver.Chrome() never succeeded; calling close() then continuing to use the instance.

Related errors


AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15). Data as JSON: /api/errors/81004b79b2b8eae0. Report an issue: GitHub.