abhigyanpatwari/GitNexus · error · ValueError
candidate destination is unreadable: {relative}: {exc}
Error message
candidate destination is unreadable: {relative}: {exc} What it means
Thrown by _replace_regular_file (evolution.py:195) when os.stat of the leaf file (dir_fd-relative, follow_symlinks=False) raises an OSError other than FileNotFoundError. The leaf exists but its metadata cannot be read — permission denied, ELOOP, or another filesystem-level error.
Source
Thrown at eval/workflow_bench/evolution.py:195
os.mkdir(part, mode=0o700, dir_fd=descriptor)
except FileExistsError:
pass
try:
child = os.open(part, directory_flags, dir_fd=descriptor)
except OSError as exc:
raise ValueError(
f"candidate destination parent must be a real directory: {relative.parent}: {exc}"
) from exc
os.close(descriptor)
descriptor = child
leaf = relative.name
try:
existing = os.stat(leaf, dir_fd=descriptor, follow_symlinks=False)
except FileNotFoundError:
existing = None
except OSError as exc:
raise ValueError(f"candidate destination is unreadable: {relative}: {exc}") from exc
if existing is not None and (stat.S_ISLNK(existing.st_mode) or not stat.S_ISREG(existing.st_mode)):
raise ValueError(f"candidate destination must be a regular non-symlink file: {relative}")
temporary = f".wfbench-overlay-{secrets.token_hex(12)}"
temp_descriptor = os.open(
temporary,
os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, "O_NOFOLLOW", 0),
0o600,
dir_fd=descriptor,
)
try:
view = memoryview(content)
while view:
written = os.write(temp_descriptor, view)
if written <= 0:
raise OSError("short write while staging candidate overlay")
view = view[written:]
os.fchmod(temp_descriptor, 0o644)View on GitHub (pinned to d540b00184)
Solutions
- Fix permissions on the leaf and its parent directory (chmod u+rw, parent u+rx).
- If the leaf is stale from a prior run, remove it so the harness creates a fresh file.
- Move the clone to a healthy local filesystem and retry.
Example fix
# before: existing leaf unreadable
# stat raises PermissionError -> 'candidate destination is unreadable'
# after: ensure the leaf is readable/removable
leaf = clone / '.claude/skills/gitnexus-work/SKILL.md'
if leaf.exists():
leaf.chmod(0o644) # or leaf.unlink() to let the harness recreate it Defensive patterns
Strategy: validation
Validate before calling
import os
from pathlib import Path
def leaf_is_accessible(clone: Path, rel: Path) -> bool:
leaf = clone / rel
if not leaf.exists() and not leaf.is_symlink():
return True
try:
os.stat(leaf, follow_symlinks=False)
return True
except OSError:
return False Type guard
null
Try / catch
try:
apply_candidate_overlay(overlay, worktree, sandbox=sandbox)
except ValueError as exc:
if 'destination is unreadable' in str(exc):
# chmod or remove the offending leaf, then retry
... Prevention
- Run the harness as the user that owns the clone.
- Reset stale clone files (chmod u+rw) before applying an overlay.
- Keep the clone on a healthy local filesystem.
When it happens
Trigger: The destination leaf already exists in the clone but stat fails due to EACCES (no permission on the parent dir or the file), ELOOP, or an I/O error from the underlying filesystem.
Common situations: Clone files left with restrictive modes from a prior sandbox run; running the harness as a different user than the one that created the clone; a failing/networked filesystem under the clone.
Related errors
- candidate destination parent must be a real directory: {rela
- candidate overlay directory is unreadable: {directory}: {exc
- Could not read ${GITNEXUS_RC_FILENAME}: ${(err as Error).mes
- 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/c89c43186b4e90fc.
Report an issue: GitHub.