{"record":{"id":"64c80c8b74bbae6f","repo":"tirth8205/code-review-graph","slug":"not-a-directory-resolved","errorCode":null,"errorMessage":"Not a directory: {resolved}","messagePattern":"Not a directory: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"code_review_graph/daemon.py","lineNumber":326,"sourceCode":"    config_path: Path | None = None,\n) -> DaemonConfig:\n    \"\"\"Add a repository to the daemon config and persist the change.\n\n    Args:\n        repo_path:   Path to the repository (will be resolved to absolute).\n        alias:       Optional short name.  Derived from dirname if *None*.\n        config_path: Explicit config file path.  Falls back to :func:`default_config_path`.\n\n    Returns:\n        The updated :class:`DaemonConfig`.\n\n    Raises:\n        ValueError: If the path is not a valid repository directory.\n    \"\"\"\n    resolved = Path(repo_path).expanduser().resolve()\n\n    if not resolved.is_dir():\n        raise ValueError(f\"Not a directory: {resolved}\")\n\n    has_repo_marker = (\n        (resolved / \".git\").exists()\n        or (resolved / \".svn\").exists()\n        or (resolved / \".code-review-graph\").exists()\n    )\n    if not has_repo_marker:\n        raise ValueError(f\"No .git, .svn, or .code-review-graph directory in {resolved}\")\n\n    effective_alias = alias or resolved.name\n\n    config = load_config(config_path)\n\n    # Check for duplicate path or alias\n    for existing in config.repos:\n        if existing.path == str(resolved):\n            logger.warning(\"Repo %s is already configured — skipping\", resolved)\n            return config","sourceCodeStart":308,"sourceCodeEnd":344,"githubUrl":"https://github.com/tirth8205/code-review-graph/blob/b58668751ab0c7670c078cf7cbd4d1f5b8e54f81/code_review_graph/daemon.py#L308-L344","documentation":"add_repo_to_config() validates the user-supplied repo path before registering it with the daemon. After expanduser/resolve, it requires the path to be an existing directory; a nonexistent path or a file yields ValueError('Not a directory: ...'). This guards the daemon's watch list against unwatchable entries.","triggerScenarios":"Calling `code-review-graph daemon add <path>` (or add_repo_to_config directly) with a typo'd path, a path to a file instead of a directory, or a path that does not exist (including broken symlinks after resolve).","commonSituations":"Typos in CLI arguments, relative paths resolved against an unexpected cwd, moved/deleted repositories, or unexpanded '~' handled incorrectly by the caller.","solutions":["Check the path exists and is a directory: ls -d <path> before adding","Use an absolute path or ensure the cwd is correct when passing a relative path","If the repo truly is missing, clone/restore it first, then retry the add"],"exampleFix":"# before\n$ code-review-graph daemon add ./my-repo-typo\nValueError: Not a directory: /home/me/my-repo-typo\n\n# after\n$ code-review-graph daemon add ~/projects/my-repo","handlingStrategy":"validation","validationCode":"from pathlib import Path\n\nrepo = Path(input_path).expanduser().resolve()\nassert repo.is_dir(), f\"not a directory: {repo}\"","typeGuard":"from pathlib import Path\n\ndef is_valid_repo_dir(p: str | Path) -> bool:\n    r = Path(p).expanduser().resolve()\n    return r.is_dir()","tryCatchPattern":"try:\n    add_repo_to_config(repo_path, alias)\nexcept ValueError as e:\n    if str(e).startswith(\"Not a directory\"):\n        # prompt user / log and skip\n        ...\n    else:\n        raise","preventionTips":["Validate paths with Path.is_dir() before calling daemon add","Prefer absolute paths in scripts to avoid cwd-dependent resolution","Check for typos and broken symlinks when adds fail"],"tags":["daemon","config","path-validation","valueerror"],"backgroundTag":"invalid-path-argument","analyzedSha":"b58668751ab0c7670c078cf7cbd4d1f5b8e54f81","analyzedAt":"2026-08-28T13:19:08.966Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}