abhigyanpatwari/GitNexus · error · ValueError
candidate overlay is not a directory: {overlay}
Error message
candidate overlay is not a directory: {overlay} What it means
Thrown by candidate_overlay_files (evolution.py:277) when overlay.resolve(strict=True) raises OSError. strict=True fails if the path or any component does not exist (or is a broken symlink). Despite the 'is not a directory' wording, this fires for any resolve failure — the overlay path is missing or unreachable.
Source
Thrown at eval/workflow_bench/evolution.py:277
command,
timeout=60,
env=build_sandbox_environment(),
)
return command, result
def candidate_overlay_files(overlay: Path) -> list[Path]:
"""Return a candidate's files after enforcing the benchmark trust boundary.
Candidates may change only the canonical repo-local skill prompts. They
cannot modify task code, tests, or verification commands and thereby game
the promotion gate.
"""
overlay = overlay.expanduser().absolute()
try:
resolved_overlay = overlay.resolve(strict=True)
except OSError as exc:
raise ValueError(f"candidate overlay is not a directory: {overlay}") from exc
if resolved_overlay != overlay:
raise ValueError(f"candidate overlay cannot traverse symlinks: {overlay}")
_require_real_directory(overlay, label="candidate overlay")
entries: list[Path] = []
pending = [overlay]
entry_count = 0
while pending:
directory = pending.pop()
child_directories: list[Path] = []
try:
iterator = os.scandir(directory)
except OSError as exc:
raise ValueError(f"candidate overlay directory is unreadable: {directory}: {exc}") from exc
with iterator:
for item in iterator:
entry_count += 1
if entry_count > MAX_CANDIDATE_ENTRIES:View on GitHub (pinned to d540b00184)
Solutions
- Verify the overlay directory exists and is reachable: assert overlay.exists() and overlay.is_dir() before calling.
- Pass an absolute path; re-check for typos and that the artifact was produced.
- Ensure the parent volume/mount is present.
Example fix
# before: path typo or missing artifact
apply_candidate_overlay(Path('overlays/candiate'), ...) # typo
# after: validate existence first
overlay = Path('overlays/candidate').resolve()
assert overlay.exists() and overlay.is_dir(), f'overlay missing: {overlay}'
apply_candidate_overlay(overlay, ...) Defensive patterns
Strategy: validation
Validate before calling
from pathlib import Path
def overlay_exists_and_is_dir(p: Path) -> bool:
return p.exists() and p.is_dir() and not p.is_symlink() Type guard
from pathlib import Path
def is_real_directory(p: Path) -> bool:
return p.exists() and p.is_dir() and not p.is_symlink() Try / catch
try:
apply_candidate_overlay(overlay, worktree, sandbox=sandbox)
except ValueError as exc:
if 'is not a directory' in str(exc):
# verify the path exists; fix typo or regenerate the artifact
... Prevention
- Assert overlay.exists() and overlay.is_dir() before calling.
- Pass absolute paths to avoid cwd-relative surprises.
- Confirm upstream artifact production actually wrote the directory.
When it happens
Trigger: The overlay path does not exist; a parent component is a broken symlink; the path points to a regular file rather than a directory; permission denied traversing to it.
Common situations: Typo or stale relative path passed as the overlay; CI deleted/moved the overlay artifact before the harness read it; pointing at a path inside an unmounted volume.
Related errors
- candidate overlay contains no files: {overlay}
- Could not read ${GITNEXUS_RC_FILENAME}: ${(err as Error).mes
- 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
AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12).
Data as JSON: /api/errors/7cbca85e84a22c47.
Report an issue: GitHub.