{"record":{"id":"09f2a10073828951","repo":"crewAIInc/crewAI","slug":"firecrawlapp-not-properly-initialized-09f2a1","errorCode":null,"errorMessage":"FirecrawlApp not properly initialized","messagePattern":"FirecrawlApp not properly initialized","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/firecrawl_search_tool/firecrawl_search_tool.py","lineNumber":111,"sourceCode":"\n                try:\n                    subprocess.run([\"uv\", \"add\", \"firecrawl-py\"], check=True)  # noqa: S607\n                    from firecrawl import FirecrawlApp\n\n                    self._firecrawl = FirecrawlApp(api_key=self.api_key)\n                except subprocess.CalledProcessError as e:\n                    raise ImportError(\"Failed to install firecrawl-py package\") from e\n            else:\n                raise ImportError(\n                    \"`firecrawl-py` package not found, please run `uv add firecrawl-py`\"\n                ) from None\n\n    def _run(\n        self,\n        query: str,\n    ) -> Any:\n        if not self._firecrawl:\n            raise RuntimeError(\"FirecrawlApp not properly initialized\")\n\n        return self._firecrawl.search(\n            query=query,\n            **self.config,\n        )\n\n\ntry:\n    from firecrawl import FirecrawlApp  # noqa: F401\n\n    if not getattr(FirecrawlSearchTool, \"_model_rebuilt\", False):\n        FirecrawlSearchTool.model_rebuild()\n        FirecrawlSearchTool._model_rebuilt = True  # type: ignore[attr-defined]\nexcept ImportError:\n    pass\n","sourceCodeStart":93,"sourceCodeEnd":127,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/firecrawl_search_tool/firecrawl_search_tool.py#L93-L127","documentation":"RuntimeError raised at the top of FirecrawlSearchTool._run when self._firecrawl is falsy, i.e. the FirecrawlApp client was never attached. As with the sibling Firecrawl tools, the constructor sets it on every success path, so this guard trips only for objects that skipped or partially completed __init__.","triggerScenarios":"Invoking _run(query) on an instance produced by __new__, model_copy, or a mock whose _firecrawl attribute is unset/None.","commonSituations":"Test harnesses mocking the tool but forgetting the client attribute; init exceptions swallowed by broad excepts leaving a zombie instance.","solutions":["Use the normal constructor: FirecrawlSearchTool(api_key=...).","For tests, assign tool._firecrawl = MagicMock() before calling _run.","Never reuse an instance whose __init__ raised."],"exampleFix":"# before\ntool = FirecrawlSearchTool.__new__(FirecrawlSearchTool)\ntool._run('query')  # RuntimeError\n\n# after\ntool = FirecrawlSearchTool(api_key=FIRECRAWL_API_KEY)\ntool._run('query')","handlingStrategy":"type-guard","validationCode":"if not getattr(tool, '_firecrawl', None):\n    raise RuntimeError('search tool has no FirecrawlApp client')","typeGuard":"def search_tool_ready(tool) -> bool:\n    return bool(getattr(tool, '_firecrawl', None))","tryCatchPattern":"try:\n    out = tool._run(query)\nexcept RuntimeError as e:\n    if 'not properly initialized' in str(e):\n        tool = FirecrawlSearchTool(api_key=KEY)\n        out = tool._run(query)\n    else:\n        raise","preventionTips":["Build tools via constructors; inject mocks for the client in tests.","Discard half-initialized objects instead of calling _run on them."],"tags":["firecrawl","initialization","defensive-check","runtime-error"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}