{"record":{"id":"7080497b8e8ff2fe","repo":"crewAIInc/crewAI","slug":"path-is-not-a-directory-source-ref","errorCode":null,"errorMessage":"Path is not a directory: {source_ref}","messagePattern":"Path is not a directory: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"lib/crewai-tools/src/crewai_tools/rag/loaders/directory_loader.py","lineNumber":32,"sourceCode":"            source_content: Directory path or URL to a directory listing\n            **kwargs: Additional options:\n                - recursive: bool (default True) - Whether to search recursively\n                - include_extensions: list - Only include files with these extensions\n                - exclude_extensions: list - Exclude files with these extensions\n                - max_files: int - Maximum number of files to process\n        \"\"\"\n        source_ref = source_content.source_ref\n\n        if source_content.is_url():\n            raise ValueError(\n                \"URL directory loading is not supported. Please provide a local directory path.\"\n            )\n\n        if not os.path.exists(source_ref):\n            raise FileNotFoundError(f\"Directory does not exist: {source_ref}\")\n\n        if not os.path.isdir(source_ref):\n            raise ValueError(f\"Path is not a directory: {source_ref}\")\n\n        return self._process_directory(source_ref, kwargs)\n\n    def _process_directory(self, dir_path: str, kwargs: dict[str, Any]) -> LoaderResult:\n        recursive: bool = kwargs.get(\"recursive\", True)\n        include_extensions: list[str] | None = kwargs.get(\"include_extensions\", None)\n        exclude_extensions: list[str] | None = kwargs.get(\"exclude_extensions\", None)\n        max_files: int | None = kwargs.get(\"max_files\", None)\n\n        files = self._find_files(\n            dir_path, recursive, include_extensions, exclude_extensions\n        )\n\n        if max_files is not None and len(files) > max_files:\n            files = files[:max_files]\n\n        all_contents = []\n        processed_files = []","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/crewAIInc/crewAI/blob/754d7323beb2fd042e33444a115ea2d5a47193f0/lib/crewai-tools/src/crewai_tools/rag/loaders/directory_loader.py#L14-L50","documentation":"Raised by DirectoryLoader.load() when the source_ref exists on disk but is not a directory (os.path.isdir fails). This catches the case where a regular file, symlink to a file, or special file is passed where a directory tree is expected. The message distinguishes it from the not-found case so the caller knows the path resolves but to the wrong kind of object.","triggerScenarios":"Passing a path to a single file (e.g. notes.txt) to DirectoryLoader instead of a file loader like TextLoader or PDFLoader; passing a symlink that points to a file; passing a device/socket path.","commonSituations":"Copy-paste from a file-loader example into DirectoryLoader; user-supplied source strings where a filename is given where a folder is expected; broken symlinks that resolve to files; picking DirectoryLoader from the loader registry because it accepts any 'source'.","solutions":["If you meant to load one file, use the matching file loader (TextLoader, PDFLoader, DOCXLoader) or point DirectoryLoader at the containing directory.","If you meant a directory, correct the path so it names the folder, not a file inside it.","Add a pre-check with os.path.isdir(source) and fail with your own clearer message."],"exampleFix":"# before\nresult = DirectoryLoader().load(SourceContent('reports/q3.pdf'))\n\n# after\nresult = PDFLoader().load(SourceContent('reports/q3.pdf'))\n# or, to ingest the whole folder:\nresult = DirectoryLoader().load(SourceContent('reports'))","handlingStrategy":"type-guard","validationCode":"import os\\n\\ndef ensure_directory(path: str) -> bool:\\n    return os.path.isdir(path) and not os.path.isfile(path)","typeGuard":"def is_directory_source(s: str) -> bool:\\n    return os.path.isdir(s)","tryCatchPattern":"try:\\n    result = loader.load(source)\\nexcept ValueError as e:\\n    if 'not a directory' in str(e):\\n        # route single files to a file loader\\n        result = pick_file_loader(s).load(source)\\n    else:\\n        raise","preventionTips":["Choose the loader by source kind, not convenience.","Route files to file loaders; keep DirectoryLoader for folders.","Check symlinks with os.path.realpath before deciding."],"tags":["filesystem","loader","rag","validation"],"backgroundTag":null,"analyzedSha":"754d7323beb2fd042e33444a115ea2d5a47193f0","analyzedAt":"2026-08-15T04:06:56.746Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}