abhigyanpatwari/GitNexus · error · ValueError
overlay destination parent is unavailable: {target}
Error message
overlay destination parent is unavailable: {target} 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. In `_open_target_parent`'s per-component walk, `os.stat(part, dir_fd=current, follow_symlinks=False)` raised `OSError`. An intermediate directory component named by `part` does not exist or is inaccessible relative to the held descriptor, so the target's parent chain cannot be walked.
Source
Thrown at eval/workflow_bench/promotion_apply.py:201
os.close(descriptor)
raise ValueError(f"repository root changed while opening: {root}") from exc
except BaseException:
os.close(descriptor)
raise
return root, descriptor
def _open_target_parent(root_descriptor: int, target: PurePosixPath) -> int:
if target.is_absolute() or not target.parts or ".." in target.parts:
raise ValueError(f"overlay destination escapes repository: {target}")
flags = os.O_RDONLY | os.O_DIRECTORY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
current = os.dup(root_descriptor)
try:
for part in target.parts[:-1]:
try:
metadata = os.stat(part, dir_fd=current, follow_symlinks=False)
except OSError as exc:
raise ValueError(f"overlay destination parent is unavailable: {target}") from exc
if stat.S_ISLNK(metadata.st_mode) or not stat.S_ISDIR(metadata.st_mode):
raise ValueError(f"overlay destination parent must not be a symlink: {target}")
try:
child = os.open(part, flags, dir_fd=current)
except OSError as exc:
raise ValueError(f"overlay destination parent changed while opening: {target}") from exc
opened = os.fstat(child)
if (
opened.st_dev,
opened.st_ino,
stat.S_IFMT(opened.st_mode),
) != (
metadata.st_dev,
metadata.st_ino,
stat.S_IFMT(metadata.st_mode),
):
os.close(child)
raise ValueError(f"overlay destination parent changed while opening: {target}")View on GitHub (pinned to d540b00184)
Solutions
- Check the target's parent exists: `Path(root / target.parent).is_dir()`.
- Create the missing mirror directory in the checkout (the API does NOT mkdir).
- Re-derive the overlay payload so it only targets existing skill paths.
Example fix
// before
apply_promoted_overlay(overlay, repo_root=root)
// after
for rel,_ in candidate_overlay_payload(overlay)[1]:
for t in mirror_targets(rel):
parent = root / t.parent
if not parent.is_dir():
raise SystemExit(f'missing parent dir: {parent}')
apply_promoted_overlay(overlay, repo_root=root) Defensive patterns
Strategy: validation
Validate before calling
def assert_parents_exist(root, payload):
for rel, _ in payload:
for t in mirror_targets(rel):
parent = root / t.parent
if not parent.is_dir():
raise ValueError(f'missing parent: {parent}')
assert_parents_exist(root, candidate_overlay_payload(overlay)[1]) Type guard
def all_parents_exist(root, payload) -> bool:
return all(
(root / t.parent).is_dir()
for rel, _ in payload for t in mirror_targets(rel)
) Try / catch
except ValueError as exc:
if 'parent is unavailable' in str(exc):
raise SystemExit(f'overlay target parent missing; create the mirror dir first: {exc}') Prevention
- Ensure the full mirror skill tree exists before promoting (the API replaces files, it does not create directories).
- Validate `all_parents_exist` against the payload before applying.
- Clone a complete checkout, not a sparse/partial one, for promotion.
When it happens
Trigger: An overlay target whose parent directory (or an intermediate component) does not exist in the checkout, or is unreadable; e.g. the overlay declares a path under a skill name that was never created.
Common situations: Promoting an overlay for a skill not yet present in the mirror roots; a partially cloned checkout missing a subdirectory; permission drop on an intermediate dir.
Related errors
- overlay destination parent must not be a symlink: {target}
- candidate destination parent must be a real directory: {rela
- candidate destination is unreadable: {relative}: {exc}
- candidate destination must be a regular non-symlink file: {r
- short write while staging candidate overlay
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/acf2f629d1cf5c0d.
Report an issue: GitHub.