{"record":{"id":"9f2a208ee39a2bb4","repo":"crewAIInc/crewAI","slug":"reading-docx-urls-requires-python-docx-install-wi","errorCode":null,"errorMessage":"Reading DOCX URLs requires python-docx. Install with: uv add python-docx","messagePattern":"Reading DOCX URLs requires python-docx\\. Install with: uv add python-docx","errorType":"exception","errorClass":"ImportError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/tools/url_read_tool/url_read_tool.py","lineNumber":274,"sourceCode":"            pages = [\n                f\"Page {number}:\\n{text}\"\n                for number, page in enumerate(document, 1)\n                if (text := page.get_text().strip())\n            ]\n        finally:\n            document.close()\n\n        if not pages:\n            return \"[PDF with no extractable text]\"\n        return \"\\n\\n\".join(pages)\n\n    @staticmethod\n    def _extract_docx(body: bytes) -> str:\n        \"\"\"Extract paragraph text from DOCX bytes.\"\"\"\n        try:\n            from docx import Document\n        except ImportError as e:\n            raise ImportError(\n                \"Reading DOCX URLs requires python-docx. Install with: \"\n                \"uv add python-docx\"\n            ) from e\n\n        document = Document(BytesIO(body))\n        return \"\\n\".join(\n            paragraph.text\n            for paragraph in document.paragraphs\n            if paragraph.text.strip()\n        )\n\n    def _extract_html(self, body: bytes, content_type: str) -> str:\n        \"\"\"Strip HTML bytes down to visible text.\"\"\"\n        try:\n            from bs4 import BeautifulSoup\n        except ImportError as e:\n            raise ImportError(\n                \"Reading HTML URLs requires beautifulsoup4. Install with: \"","sourceCodeStart":256,"sourceCodeEnd":292,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/tools/url_read_tool/url_read_tool.py#L256-L292","documentation":"UrlReadTool's DOCX extraction lazily imports 'python-docx' (from docx import Document) inside _extract_docx. When the tool fetches a Word document URL and python-docx is absent, ImportError is raised with the install command.","triggerScenarios":"Calling UrlReadTool on a URL serving a .docx / application/vnd.openxmlformats-officedocument.wordprocessingml.document response without python-docx installed.","commonSituations":"Minimal crewai-tools installs missing optional document parsers; intranet crawls that encounter Word documents unexpectedly; CI environments trimmed of extras.","solutions":["Install the dependency: uv add python-docx (or pip install python-docx).","Include python-docx in project dependencies if DOCX URLs are in scope.","Pre-check the URL extension/content type and skip unsupported types when the parser lib is missing."],"exampleFix":"# before\ntool.run('https://example.com/spec.docx')  # ImportError: requires python-docx\n\n# after\n# shell: uv add python-docx\ntool.run('https://example.com/spec.docx')","handlingStrategy":"validation","validationCode":"import importlib.util\n\nif not importlib.util.find_spec('docx'):\n    raise SystemExit('UrlReadTool needs python-docx for DOCX URLs: uv add python-docx')","typeGuard":null,"tryCatchPattern":"try:\n    text = tool.run(url)\nexcept ImportError as e:\n    if 'python-docx' in str(e):\n        text = '[skipped: python-docx not installed]'\n    else:\n        raise","preventionTips":["Add python-docx when document URLs are in scope.","Check find_spec('docx') (module name differs from package name) at startup.","Surface missing-parser errors distinctly from fetch errors in logs."],"tags":["dependencies","docx","python-docx","url-read"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}