abhigyanpatwari/GitNexus · error · ValueError
repository root is unavailable: {root}
Error message
repository root is unavailable: {root} What it means
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.
Source
Thrown at eval/workflow_bench/promotion_apply.py:156
stat.S_IMODE(value.st_mode),
)
if (
stat.S_ISLNK(final.st_mode)
or not stat.S_ISREG(final.st_mode)
or not (identity(before) == identity(opened) == identity(after) == identity(final))
):
raise ValueError(f"overlay destination changed while being read: {target}")
return b"".join(chunks), opened.st_mode
def _open_repository_root(repo_root: Path) -> tuple[Path, int]:
root = repo_root.expanduser().absolute()
try:
metadata = root.lstat()
resolved = root.resolve(strict=True)
except OSError as exc:
raise ValueError(f"repository root is unavailable: {root}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise ValueError(f"repository root must be a real directory: {root}")
if resolved != root:
raise ValueError(f"repository root must not traverse symlinks: {root}")
flags = os.O_RDONLY | os.O_DIRECTORY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
try:
descriptor = os.open(root, flags)
except OSError as exc:
raise ValueError(f"repository root changed while opening: {root}") from exc
try:
opened = os.fstat(descriptor)
final = root.lstat()
final_resolved = root.resolve(strict=True)
def identity(value: os.stat_result) -> tuple[int, int, int]:
return value.st_dev, value.st_ino, stat.S_IFMT(value.st_mode)
if (View on GitHub (pinned to d540b00184)
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.
Example fix
// before
apply_promoted_overlay(overlay, repo_root=Path('repo'))
// after
root = Path('repo').resolve()
if not root.is_dir():
raise SystemExit(f'repo_root is not an accessible directory: {root}')
apply_promoted_overlay(overlay, repo_root=root) Defensive patterns
Strategy: validation
Validate before calling
def safe_repo_root(p):
root = Path(p).expanduser().absolute()
if not root.is_dir() or os.access(root, os.R_OK | os.X_OK):
return root
raise ValueError(f'repo_root not stat-resolvable: {root}')
# call before the API
root = safe_repo_root(repo_root) Type guard
def is_accessible_dir(p: str) -> bool:
root = Path(p).expanduser().absolute()
try:
return root.is_dir() and os.access(root, os.R_OK | os.X_OK)
except OSError:
return False Try / catch
except ValueError as exc:
if 'repository root is unavailable' in str(exc):
log.error('repo_root inaccessible: %s', exc)
# do NOT retry blindly; surface a config error to the operator
raise Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Could not read ${GITNEXUS_RC_FILENAME}: ${(err as Error).mes
- ${TRUSTED_CACHE_DIRECTORY_ENV} must name a pre-existing prot
- candidate destination is unreadable: {relative}: {exc}
- candidate overlay directory is unreadable: {directory}: {exc
- transcript artifact parent must be owner-only: {current}
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/11bde286d51ee0c4.
Report an issue: GitHub.