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
- Create a fresh ScrapegraphScrapeTool instance for each scraping session instead of reusing a spent one.
- Verify the tool was constructed through its normal constructor (with api_key) so model_post_init ran and _client was set.
- 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
- Prefer a fresh ScrapegraphScrapeTool per scraping session (the finally block closes the client).
- Construct tools via their normal constructor so model_post_init runs.
- Add a smoke-test scrape after tool creation to fail fast on broken init.
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
- Driver not initialized. Call _run first.
- MCP server not started, run `mcp_server.start()` first befor
- Failed to initialize {self.config.provider} embedding servic
- Failed to run ApifyActorsTool {self.name}. Please check your
- FirecrawlApp not properly initialized
AI-assisted analysis of crewAIInc/crewAI@754d7323be (2026-08-15).
Data as JSON: /api/errors/ae760ecb9d0796cf.
Report an issue: GitHub.