{"record":{"id":"8617b1aba94d2ea9","repo":"crewAIInc/crewAI","slug":"source-must-be-a-valid-file-path-or-url-got-sou","errorCode":null,"errorMessage":"Source must be a valid file path or URL, got: {source_content.source}","messagePattern":"Source must be a valid file path or URL, got: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/rag/loaders/docx_loader.py","lineNumber":30,"sourceCode":"        try:\n            from docx import Document as DocxDocument\n        except ImportError as e:\n            raise ImportError(\n                \"python-docx is required for DOCX loading. Install with: 'uv pip install python-docx' or pip install crewai-tools[rag]\"\n            ) from e\n\n        source_ref = source_content.source_ref\n\n        if source_content.is_url():\n            temp_file = self._download_from_url(source_ref, kwargs)\n            try:\n                return self._load_from_file(temp_file, source_ref, DocxDocument)\n            finally:\n                os.unlink(temp_file)\n        elif source_content.path_exists():\n            return self._load_from_file(source_ref, source_ref, DocxDocument)\n        else:\n            raise ValueError(\n                f\"Source must be a valid file path or URL, got: {source_content.source}\"\n            )\n\n    @staticmethod\n    def _download_from_url(url: str, kwargs: dict[str, Any]) -> str:\n        headers = kwargs.get(\n            \"headers\",\n            {\n                \"Accept\": \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n                \"User-Agent\": \"Mozilla/5.0 (compatible; crewai-tools DOCXLoader)\",\n            },\n        )\n\n        try:\n            response = safe_get(url, headers=headers, timeout=30)\n            response.raise_for_status()\n\n            # Create temporary file to save the DOCX content","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/rag/loaders/docx_loader.py#L12-L48","documentation":"Raised by DOCXLoader.load() when the source is neither recognized as a URL nor an existing local path. The loader branches on source_content.is_url() then source_content.path_exists(); the else branch rejects anything else — sources that are neither an http(s) URL nor a file present on disk.","triggerScenarios":"Passing a bare filename that does not exist in the current working directory; a malformed URL missing the scheme (example.com/file.docx); a Windows UNC or path with unexpanded variables; an empty or whitespace-only source string; a file path with a typo.","commonSituations":"Relative paths evaluated from an unexpected cwd (notebooks, launched services); URLs pasted without https://; paths built from untrusted or unvalidated user input; files that were deleted between listing and loading; S3/gs:// URIs that this local/URL-only loader does not support.","solutions":["Normalize the source first: expand ~ and env vars, make relative paths absolute against a known base, and prefix URLs with https://.","Verify existence with Path(source).expanduser().resolve().exists() before calling load; if it is a remote URI scheme like s3://, download the file first.","For remote storage, sync the object to a temp file and pass the local path or a public https URL."],"exampleFix":"# before\nresult = DOCXLoader().load(SourceContent('~/reports/spec.docx'))  # literal ~ not expanded\n\n# after\nfrom pathlib import Path\nsrc = str(Path('~/reports/spec.docx').expanduser().resolve())\nassert Path(src).is_file(), src\nresult = DOCXLoader().load(SourceContent(src))","handlingStrategy":"validation","validationCode":"from pathlib import Path\\n\\ndef normalize_source(s: str) -> str:\\n    s = Path(s).expanduser()\\n    if s.suffix or '/' in str(s):\\n        return str(s.resolve()) if s.exists() else ('https://' + s if '.' in s else s)\\n    return str(s)","typeGuard":"from pathlib import Path\\n\\ndef is_loadable_docx_source(s: str) -> bool:\\n    return s.startswith(('http://', 'https://')) or Path(s).expanduser().is_file()","tryCatchPattern":"try:\\n    result = DOCXLoader().load(source)\\nexcept ValueError as e:\\n    if 'must be a valid file path or URL' in str(e):\\n        raise FileNotFoundError(source.source) from e\\n    raise","preventionTips":["Expand ~ and env vars before building sources.","Reject unknown URI schemes early (s3://, gs:// need download first).","Log the exact source string on failure to catch invisible whitespace."],"tags":["validation","filesystem","loader","docx"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}