{"record":{"id":"2271236453c949df","repo":"cocoindex-io/cocoindex","slug":"path-is-not-a-directory-root-resolved","errorCode":null,"errorMessage":"Path is not a directory: {root_resolved}","messagePattern":"Path is not a directory: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/connectors/localfs/_source.py","lineNumber":110,"sourceCode":"        path: FilePath | Path | ContextKey[Path],\n        *,\n        live: bool = False,\n        recursive: bool = False,\n        path_matcher: FilePathMatcher | None = None,\n        rescan_interval: datetime.timedelta | None = _DEFAULT_RESCAN_INTERVAL,\n    ) -> None:\n        self._root_path = to_file_path(path)\n        self._live = live\n        self._recursive = recursive\n        self._path_matcher = path_matcher or MatchAllFilePathMatcher()\n        self._rescan_interval = rescan_interval\n\n    def _walk_sync(self) -> Iterator[File]:\n        \"\"\"Synchronously walk the directory and yield File objects (internal helper).\"\"\"\n        root_resolved = self._root_path.resolve()\n\n        if not root_resolved.is_dir():\n            raise ValueError(f\"Path is not a directory: {root_resolved}\")\n\n        dirs_to_process: list[Path] = [root_resolved]\n\n        while dirs_to_process:\n            current_dir = dirs_to_process.pop()\n\n            try:\n                entries = list(current_dir.iterdir())\n            except PermissionError:\n                continue\n\n            subdirs: list[Path] = []\n\n            for entry in entries:\n                try:\n                    relative_path = entry.relative_to(root_resolved)\n                except ValueError:\n                    # Should not happen, but skip if it does","sourceCodeStart":92,"sourceCodeEnd":128,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/connectors/localfs/_source.py#L92-L128","documentation":"localfs directory walking resolves the root path and requires it to be an existing directory. If the resolved root is not a directory (missing path, a file, or a broken symlink), _walk_sync raises ValueError before yielding any File objects. The error surfaces when iterating the DirSource (via __aiter__).","triggerScenarios":"Creating localfs.dir(...) / DirSource with a root path that does not exist, points to a regular file, or is a dangling symlink, then iterating it (async for ... in source, or walk_dir items consumed by mount_each).","commonSituations":"Typo in the source directory path; pointing the pipeline at a file instead of a directory; the directory was deleted/moved before the run; relative path resolved from an unexpected working directory (e.g. different cwd in CI).","solutions":["Fix the root path to point to an existing directory","Create the directory if it is expected to exist (mkdir -p) before running the pipeline","If the path is supposed to be a file source, use the appropriate file-based API instead of a directory walk","Make the path absolute (pathlib.Path(...).resolve()) and verify is_dir() before wiring it into the source"],"exampleFix":"// before\nsource = localfs.walk_dir(\"./documets\")  # typo -> not a directory\n// after\nroot = pathlib.Path(\"./documents\").resolve()\nassert root.is_dir(), root\nsource = localfs.walk_dir(root, recursive=True, path_matcher=PatternFilePathMatcher([\"**/*.md\"]))","handlingStrategy":"validation","validationCode":"from pathlib import Path\nroot = Path(path).resolve()\nif not root.is_dir():\n    raise NotADirectoryError(f\"source root is not a directory: {root}\")","typeGuard":"def is_existing_dir(p) -> bool:\n    from pathlib import Path\n    try:\n        return Path(p).resolve().is_dir()\n    except OSError:\n        return False","tryCatchPattern":"try:\n    async for f in source:\n        ...\nexcept ValueError as e:\n    if str(e).startswith(\"Path is not a directory\"):\n        logger.error(\"fix --sourcedir: %s\", e)\n        sys.exit(2)\n    raise","preventionTips":["Resolve relative paths against an explicit base directory, not the ambient cwd","Check the path exists and is a directory at app startup (fail fast in main)","Use absolute paths in config files and CI env vars","Verify the directory survives until the run finishes (mount points, tmpdirs)"],"tags":["localfs","filesystem","path"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}