{"record":{"id":"83f455b542fa27fd","repo":"crewAIInc/crewAI","slug":"pdf-support-requires-pymupdf-install-with-uv-add","errorCode":null,"errorMessage":"PDF support requires pymupdf. Install with: uv add pymupdf","messagePattern":"PDF support requires pymupdf\\. Install with: uv add pymupdf","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/rag/loaders/pdf_loader.py","lineNumber":86,"sourceCode":"\n    def load(self, source: SourceContent, **kwargs: Any) -> LoaderResult:  # type: ignore[override]\n        \"\"\"Load and extract text from a PDF file or URL.\n\n        Args:\n            source: The source content containing the PDF file path or URL.\n\n        Returns:\n            LoaderResult with extracted text content.\n\n        Raises:\n            FileNotFoundError: If the PDF file doesn't exist.\n            ImportError: If required PDF libraries aren't installed.\n            ValueError: If the PDF cannot be read or downloaded.\n        \"\"\"\n        try:\n            import pymupdf  # type: ignore[import-untyped]\n        except ImportError as e:\n            raise ImportError(\n                \"PDF support requires pymupdf. Install with: uv add pymupdf\"\n            ) from e\n\n        file_path = source.source\n        is_url = self._is_url(file_path)\n\n        if is_url:\n            source_name = Path(urlparse(file_path).path).name or \"downloaded.pdf\"\n        else:\n            source_name = Path(file_path).name\n\n        text_content: list[str] = []\n        metadata: dict[str, Any] = {\n            \"source\": file_path,\n            \"file_name\": source_name,\n            \"file_type\": \"pdf\",\n        }\n","sourceCodeStart":68,"sourceCodeEnd":104,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/rag/loaders/pdf_loader.py#L68-L104","documentation":"Raised by PDFLoader.load() when pymupdf (fitz) is not installed. The import happens lazily inside load(), so environments without optional PDF support fail only when a PDF is actually loaded; the error tells you to add pymupdf and chains the original ImportError.","triggerScenarios":"Calling PDFLoader().load(...) where crewai-tools was installed without the rag extra containing pymupdf; fresh minimal virtualenvs; dependency pruning in slim containers or after lockfile updates.","commonSituations":"Minimal `pip install crewai-tools` installs in CI; uv projects where the extra was never added; teams assuming PDF support is bundled in core; Docker images built from scratch layers that dropped optional deps.","solutions":["Install the dependency: `uv add pymupdf` or `pip install pymupdf` (or `pip install crewai-tools[rag]`).","Refresh the whole environment from the lockfile after adding the extra.","Guard optional ingestion paths behind importlib.util.find_spec('pymupdf') and skip PDF sources with a clear warning when absent."],"exampleFix":"# before\nresult = PDFLoader().load(SourceContent('manual.pdf'))  # ImportError\n\n# after\n# terminal: uv add pymupdf\nimport importlib.util\nif importlib.util.find_spec('pymupdf') is None:\n    raise RuntimeError('PDF ingestion disabled: run `uv add pymupdf`')\nresult = PDFLoader().load(SourceContent('manual.pdf'))","handlingStrategy":"validation","validationCode":"import importlib.util\\n\\ndef pdf_supported() -> bool:\\n    return importlib.util.find_spec('pymupdf') is not None","typeGuard":null,"tryCatchPattern":"try:\\n    result = PDFLoader().load(source)\\nexcept ImportError as e:\\n    raise RuntimeError('PDF ingestion unavailable: uv add pymupdf') from e","preventionTips":["Include pymupdf in every image/env that touches PDFs.","Startup-check optional deps once, not per document.","Keep a capability manifest of optional formats your deployment supports."],"tags":["pdf","dependencies","import","loader"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}