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

  1. Fix permissions on the leaf and its parent directory (chmod u+rw, parent u+rx).
  2. If the leaf is stale from a prior run, remove it so the harness creates a fresh file.
  3. 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

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


AI-assisted analysis of abhigyanpatwari/GitNexus@d540b00184 (2026-08-12). Data as JSON: /api/errors/c89c43186b4e90fc. Report an issue: GitHub.