{"record":{"id":"11bde286d51ee0c4","repo":"abhigyanpatwari/GitNexus","slug":"repository-root-is-unavailable-root","errorCode":null,"errorMessage":"repository root is unavailable: {root}","messagePattern":"repository root is unavailable: (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"eval/workflow_bench/promotion_apply.py","lineNumber":156,"sourceCode":"            stat.S_IMODE(value.st_mode),\n        )\n\n    if (\n        stat.S_ISLNK(final.st_mode)\n        or not stat.S_ISREG(final.st_mode)\n        or not (identity(before) == identity(opened) == identity(after) == identity(final))\n    ):\n        raise ValueError(f\"overlay destination changed while being read: {target}\")\n    return b\"\".join(chunks), opened.st_mode\n\n\ndef _open_repository_root(repo_root: Path) -> tuple[Path, int]:\n    root = repo_root.expanduser().absolute()\n    try:\n        metadata = root.lstat()\n        resolved = root.resolve(strict=True)\n    except OSError as exc:\n        raise ValueError(f\"repository root is unavailable: {root}\") from exc\n    if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):\n        raise ValueError(f\"repository root must be a real directory: {root}\")\n    if resolved != root:\n        raise ValueError(f\"repository root must not traverse symlinks: {root}\")\n    flags = os.O_RDONLY | os.O_DIRECTORY | getattr(os, \"O_CLOEXEC\", 0) | getattr(os, \"O_NOFOLLOW\", 0)\n    try:\n        descriptor = os.open(root, flags)\n    except OSError as exc:\n        raise ValueError(f\"repository root changed while opening: {root}\") from exc\n    try:\n        opened = os.fstat(descriptor)\n        final = root.lstat()\n        final_resolved = root.resolve(strict=True)\n\n        def identity(value: os.stat_result) -> tuple[int, int, int]:\n            return value.st_dev, value.st_ino, stat.S_IFMT(value.st_mode)\n\n        if (","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/abhigyanpatwari/GitNexus/blob/d540b00184d71a896261ee02670da9a92d59d8f7/eval/workflow_bench/promotion_apply.py#L138-L174","documentation":"All errors below are raised by internal helpers of `eval/workflow_bench/promotion_apply.py` and propagate to the caller of the public entry points: `apply_promoted_overlay(overlay, repo_root, *, expected_digest, expected_target_bases)`, `destination_base_digests(overlay, repo_root)`, `committed_destination_base_digests(overlay, repo_root, *, ref)` and `freeze_overlay(overlay, destination)`. The module applies promoted skill overlays across the canonical skill tree plus its shipped mirrors (`gitnexus/skills`, `gitnexus-claude-plugin/skills`) in a TOCTOU-hardened, symlink-rejecting, descriptor-bound transaction. `_open_repository_root` opens the transaction by calling `root.lstat()` and `root.resolve(strict=True)` (after `.expanduser().absolute()`). Any `OSError` (ENOENT, EACCES, ELOOP, ESTALE on NFS, etc.) from either call is wrapped into this `ValueError`. It means the configured `repo_root` could not be stat-resolved at all, so no descriptor can be bound.","triggerScenarios":"Calling any public entry with a `repo_root` that does not exist, is on an unmounted/stale filesystem, or is unreadable by the process (EACCES/EPERM).","commonSituations":"Wrong CWD when a relative root was expanded; repo cloned to a temp dir that was removed; running under a restricted user/container that lacks read access to the checkout; NFS/CIFS mount dropped mid-run.","solutions":["Confirm the path exists: run `repo_root.exists()` and print `repo_root.absolute()`.","Check the filesystem is mounted and readable (`os.access(root, os.R_OK | os.X_OK)`).","Pass an absolute, existing checkout path explicitly instead of relying on the `REPO_ROOT` default derived from `__file__`.","Re-run after fixing mount/permission problems."],"exampleFix":"// before\napply_promoted_overlay(overlay, repo_root=Path('repo'))\n// after\nroot = Path('repo').resolve()\nif not root.is_dir():\n    raise SystemExit(f'repo_root is not an accessible directory: {root}')\napply_promoted_overlay(overlay, repo_root=root)","handlingStrategy":"validation","validationCode":"def safe_repo_root(p):\n    root = Path(p).expanduser().absolute()\n    if not root.is_dir() or os.access(root, os.R_OK | os.X_OK):\n        return root\n    raise ValueError(f'repo_root not stat-resolvable: {root}')\n# call before the API\nroot = safe_repo_root(repo_root)","typeGuard":"def is_accessible_dir(p: str) -> bool:\n    root = Path(p).expanduser().absolute()\n    try:\n        return root.is_dir() and os.access(root, os.R_OK | os.X_OK)\n    except OSError:\n        return False","tryCatchPattern":"except ValueError as exc:\n    if 'repository root is unavailable' in str(exc):\n        log.error('repo_root inaccessible: %s', exc)\n        # do NOT retry blindly; surface a config error to the operator\n        raise","preventionTips":["Always pass an absolute, existing checkout path to the public entry points.","Verify the filesystem/mount is healthy before running promotion in CI.","Run promotion as a user with read+execute on every component of the root path."],"tags":["filesystem","configuration","repository-root","permissions"],"backgroundTag":null,"analyzedSha":"d540b00184d71a896261ee02670da9a92d59d8f7","analyzedAt":"2026-08-12T19:50:25.132Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}