abhigyanpatwari/GitNexus · error · SandboxError

sandbox_copy path is unavailable: {relative}: {exc}

Error message

sandbox_copy path is unavailable: {relative}: {exc}

What it means

Raised by _open_child when os.stat(name, dir_fd=<parent>, follow_symlinks=False) raises OSError while walking a declared sandbox_copy path from the repo root via _open_relative. The original OSError (ENOENT, EACCES, EPERM, ENOTDIR, etc.) is chained in the message after the relative path. This is the catch-all for any path component that cannot be inspected during snapshot capture.

Source

Thrown at eval/workflow_bench/task_assets.py:628

            os.close(current)
            current = child
        return current
    except BaseException:
        os.close(current)
        raise


def _open_child(
    parent_descriptor: int,
    name: str,
    relative: PurePosixPath,
    *,
    require_directory: bool = False,
) -> int:
    try:
        metadata = os.stat(name, dir_fd=parent_descriptor, follow_symlinks=False)
    except OSError as exc:
        raise SandboxError(f"sandbox_copy path is unavailable: {relative}: {exc}") from exc
    if stat.S_ISLNK(metadata.st_mode):
        raise SandboxError(f"sandbox_copy must not traverse a symlink: {relative}")
    if require_directory and not stat.S_ISDIR(metadata.st_mode):
        raise SandboxError(f"sandbox_copy parent must be a directory: {relative}")
    if not (stat.S_ISDIR(metadata.st_mode) or stat.S_ISREG(metadata.st_mode)):
        raise SandboxError(f"sandbox_copy accepts only regular files and directories: {relative}")
    flags = os.O_RDONLY | getattr(os, "O_CLOEXEC", 0) | getattr(os, "O_NOFOLLOW", 0)
    if stat.S_ISDIR(metadata.st_mode):
        flags |= os.O_DIRECTORY
    else:
        flags |= getattr(os, "O_NONBLOCK", 0)
    try:
        descriptor = os.open(name, flags, dir_fd=parent_descriptor)
    except OSError as exc:
        raise SandboxError(f"sandbox_copy path changed or is unreadable: {relative}: {exc}") from exc
    opened = os.fstat(descriptor)
    if not (stat.S_ISDIR(opened.st_mode) or stat.S_ISREG(opened.st_mode)):
        os.close(descriptor)

View on GitHub (pinned to d540b00184)

Solutions

  1. Verify the declared path exists at the resolved SHA: `git -C <repo> cat-file -e <sha>:<path>`
  2. Check permissions on the worktree and every parent: `namei -l <repo>/<path>`
  3. Confirm the worktree is not sparse: `git -C <repo> sparse-checkout list` and re-checkout fully if needed
  4. Correct the task declaration to point at a path present at that SHA
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def declared_paths_exist(repo: Path, resolved_sha: str, declarations: list[str]) -> list[str]:
    missing = []
    for decl in declarations:
        p = repo / decl
        try:
            if not p.lstat(strict=True):
                missing.append(decl)
        except (FileNotFoundError, NotADirectoryError, PermissionError) as exc:
            missing.append(f"{decl}: {exc}")
    return missing
# call before TaskAssetCache.prepare(...); abort if non-empty

Try / catch

from eval.workflow_bench.proposer_sandbox import SandboxError

try:
    snapshot = cache.prepare(task, repo=repo, resolved_sha=sha)
except SandboxError as exc:
    if "path is unavailable" in str(exc):
        # declaration/permission problem; do not retry with the same inputs
        raise SystemExit(f"sandbox_copy declaration invalid: {exc}") from exc
    raise

Prevention

When it happens

Trigger: A sandbox_copy declaration names a path that does not exist at the resolved_sha; a parent dir lacks read/execute permission for the harness process; a path component is a regular file blocking further directory traversal (ENOTDIR); the worktree was partially checked out (sparse).

Common situations: Task YAML references a file renamed/removed between commit pins; running the harness as a user without read access to the worktree; a typo in the declaration path; sparse-checkout excluded the declared subtree.

Related errors


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