crewAIInc/crewAI · error · RuntimeError

Client not initialized

Error message

Client not initialized

What it means

Raised as RuntimeError by ScrapegraphScrapeTool._run when self._client is None at call time. The client is created during tool initialization (model_post_init); if construction failed partway, the tool was built via __class__ deserialization that skips post-init, or the client was already closed by a previous run (the finally block closes it), _client will be None. Note: this check sits inside the try, so the message is re-wrapped only if not already a RuntimeError path — it propagates directly as 'Client not initialized'.

Source

Thrown at lib/crewai-tools/src/crewai_tools/tools/scrapegraph_scrape_tool/scrapegraph_scrape_tool.py:176

    def _run(
        self,
        **kwargs: Any,
    ) -> Any:
        website_url = kwargs.get("website_url", self.website_url)
        user_prompt = (
            kwargs.get("user_prompt", self.user_prompt)
            or "Extract the main content of the webpage"
        )

        if not website_url:
            raise ValueError("website_url is required")

        self._validate_url(website_url)

        try:
            if self._client is None:
                raise RuntimeError("Client not initialized")
            return self._client.smartscraper(
                website_url=website_url,
                user_prompt=user_prompt,
            )

        except RateLimitError:
            raise  # Re-raise rate limit errors
        except Exception as e:
            raise RuntimeError(f"Scraping failed: {e!s}") from e
        finally:
            # Always close the client
            if self._client is not None:
                self._client.close()

View on GitHub (pinned to 754d7323be)

Solutions

  1. Create a fresh ScrapegraphScrapeTool instance for each scraping session instead of reusing a spent one.
  2. Verify the tool was constructed through its normal constructor (with api_key) so model_post_init ran and _client was set.
  3. If reuse is required, re-initialize the client before the next call rather than calling _run on the stale instance.

Example fix

# before
tool = ScrapegraphScrapeTool(api_key=KEY)
for url in urls:
    tool.run(website_url=url)  # client closed by prior run's finally block

# after: fresh tool per call
for url in urls:
    ScrapegraphScrapeTool(api_key=KEY).run(website_url=url)
Defensive patterns

Strategy: validation

Validate before calling

def tool_ready(tool) -> bool:
    client = getattr(tool, "_client", None)
    return client is not None and hasattr(client, "smartscraper")

Try / catch

try:
    out = tool.run(website_url=url)
except RuntimeError as e:
    if "Client not initialized" in str(e):
        tool = ScrapegraphScrapeTool(api_key=KEY)  # rebuild and retry once
        out = tool.run(website_url=url)
    else:
        raise

Prevention

When it happens

Trigger: Calling tool._run() after a previous invocation finished (the finally block calls self._client.close(), and depending on client implementation the reference may be invalidated); constructing the tool in a way that skips model_post_init; a partially failed __init__ that left _client unset.

Common situations: Reusing one ScrapegraphScrapeTool instance for multiple sequential calls in a long-lived crew; deserializing a tool from a config/dict; an exception during init that was swallowed by framework retry logic.

Related errors


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